Skip to content

feat: IDL support for custom vector length discriminators#4148

Open
Otter-0x4ka5h wants to merge 11 commits into
otter-sec:masterfrom
Otter-0x4ka5h:anchor#4076
Open

feat: IDL support for custom vector length discriminators#4148
Otter-0x4ka5h wants to merge 11 commits into
otter-sec:masterfrom
Otter-0x4ka5h:anchor#4076

Conversation

@Otter-0x4ka5h

Copy link
Copy Markdown
Member

Anchor IDLs now support vectors with custom length discriminators (u8, u16, or u32), not just the default u32. This helps optimize account size for programs that use compact vectors.

Fixes #4076

@vercel

vercel Bot commented Dec 22, 2025

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Solana Foundation Team on Vercel.

A member of the Team first needs to authorize it.

@acheroncrypto acheroncrypto left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you seen #4076 (comment) ?

@acheroncrypto acheroncrypto added idl related to the IDL, either program or client side feature labels Dec 22, 2025
@0x4ka5h

0x4ka5h commented Dec 22, 2025

Copy link
Copy Markdown
Collaborator

@acheroncrypto sorry for the confusion here, will make changes. I think I pushed the wrong commit. was implemented with

impl IdlSerialization {
    /// Returns the number of bytes used for Vec length prefix in this serialization format.
    pub fn vec_length_bytes(&self) -> usize {
        match self {
            IdlSerialization::Borsh => 4,
            IdlSerialization::BorshU8 => 1,
            IdlSerialization::BorshU16 => 2,
            IdlSerialization::Bytemuck | IdlSerialization::BytemuckUnsafe => {
                8
            }
            IdlSerialization::Custom(_) => {
                4
            }
        }
    }
}

@0x4ka5h

0x4ka5h commented Dec 22, 2025

Copy link
Copy Markdown
Collaborator

Have you seen #4076 (comment) ?

re-pushed the correct changes

@acheroncrypto acheroncrypto left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I think the approach is correct, but there are a few more things that need to get addressed:

  • The serialization should apply to all unsized types; otherwise, it would be very unintuitive (on-chain programs can't handle more than 2 bytes length borsh de/serialization anyway)

  • How to use the new serialization specs?

    • In programs, how to use them without having to manually implement the de/serialization?
    • How to include this information (the serialization field) in the IDL conveniently?

    Perhaps something like a generic #[serialization] attribute or a specific #[custom_borsh] similar to the #[zero_copy] attribute?

  • declare_program! also needs to support these new serialization methods, e.g. in:

    https://github.com/solana-foundation/anchor/blob/d7ace7a47d9720386d5ddc1690f358e2d1d33ff5/lang/attribute/program/src/declare_program/common.rs#L133-L138

    Depending on the resolution of the last point, something like:

    IdlSerialization::BorshU8 => quote!(#[custom_borsh(u8)]),
    IdlSerialization::BorshU16 => quote!(#[custom_borsh(u16)]),

Comment thread .github/workflows/reusable-tests.yaml Outdated
Comment thread cli/src/lib.rs Outdated
Comment thread idl/spec/Cargo.toml Outdated
Comment thread idl/spec/src/lib.rs Outdated
Comment thread idl/spec/src/lib.rs Outdated
Comment thread ts/packages/anchor/src/coder/borsh/idl.ts Outdated
Comment thread ts/packages/anchor/src/coder/borsh/idl.ts Outdated
Comment thread ts/packages/anchor/src/coder/borsh/idl.ts Outdated
Comment thread ts/packages/anchor/src/coder/borsh/idl.ts Outdated
Comment thread ts/packages/anchor/src/coder/borsh/instruction.ts Outdated
@vercel

vercel Bot commented Jan 17, 2026

Copy link
Copy Markdown

Deployment failed with the following error:

The provided GitHub repository does not contain the requested branch or commit reference. Please ensure the repository is not empty.

@hacktron-app hacktron-app Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 4 files

Severity Count
🟡 Medium 3
🟢 Low 1
Comments Outside Diff (4)

🟡 Medium: Incorrect owner validation in init_if_needed for token accounts

Location: lang/syn/src/codegen/accounts/constraints.rs:597-1177

In generate_constraint_init_group for InitKind::Token, the if_needed logic captures the account's owner before the initialization CPI. If the account is being initialized (i.e., it was previously owned by the system program), the subsequent validation check owner_program != &token_program.key() compares the original owner (system program) against the expected owner (token program). This will cause the validation to fail for any account initialized via init_if_needed in this context, potentially rendering the feature unusable or causing unexpected transaction failures.


🟡 Medium: Stack Overflow via Deeply Nested Array Types in IDL Parsing

Location: idl/spec/src/lib.rs:384-433

The array_from_str function in anchor/idl/spec/src/lib.rs uses recursion to parse nested array types (e.g., [[[[u8; 1]; 1]; 1]; 1]). An attacker providing a deeply nested type string can trigger a stack overflow, leading to a denial-of-service (DoS) condition. While this is a parsing function, if it is exposed to user-provided IDL definitions, it can be exploited.


🟢 Low: Client-side panic via malformed RPC log signature

Duplicate of: Unsafe use of unwrap() in log parsing logic leading to potential DoS

Location: client/src/lib.rs:808-849

The parse_logs_response function uses .unwrap() when parsing the transaction signature from the RPC node's response (logs.value.signature.parse().unwrap()). If a client is configured to connect to a malicious or compromised RPC node, the node can return an invalid signature string, causing the client application to panic and crash. This results in a denial-of-service for the client.


🟡 Medium: Unbounded loop in Borsh deserialization for zero-span layouts

Location: ts/packages/borsh/src/index.ts:278-322

The decodeCollectionValues function in anchor/ts/packages/borsh/src/index.ts fails to validate the count parameter when elementLayout.span is 0. If a malicious payload specifies a very large count for a layout with a zero-byte span, the loop will execute count times, leading to excessive CPU consumption and a potential Denial of Service (DoS). While the loop itself does not allocate memory proportional to count in this specific implementation, the repeated execution of elementLayout.decode and the loop overhead for a large count can block the event loop or consume significant compute resources.

Steps to Reproduce

  1. Define a layout with span 0.
  2. Create a buffer with a large length prefix (e.g., 0xFFFFFFFF).
  3. Attempt to decode this buffer using a collection layout (vec, array, map) containing the zero-span layout.
  4. Observe the CPU usage spike as the loop executes without consuming any bytes.
# This is a conceptual representation of the trigger.
# Assuming a layout exists where span is 0.
# Buffer: [0xFF, 0xFF, 0xFF, 0xFF, ...] (4 bytes for count)
# The code will loop 4,294,967,295 times.
# No script needed, the vulnerability is a logic flaw in the validation check.
# An attacker provides a buffer where the length prefix is a large number (e.g., 0xFFFFFFFF)
# and the following data structure has a zero-span layout.
# The `assertCollectionFitsRemaining` will return without throwing, 
# and the subsequent loop in `decodeCollectionValues` will execute 4 billion times.
N/A

PoC Url: N/A

View full scan results

@0x4ka5h 0x4ka5h requested a review from swaroop-osec May 29, 2026 10:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature idl related to the IDL, either program or client side

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IDL Support for Custom Vector Length Discriminators

3 participants