Skip to content

MINOR: [c] reject out-of-range union discriminant in resolver.c - #3904

Open
arib06 wants to merge 1 commit into
apache:mainfrom
arib06:c-resolver-union-discriminant-bounds
Open

MINOR: [c] reject out-of-range union discriminant in resolver.c#3904
arib06 wants to merge 1 commit into
apache:mainfrom
arib06:c-resolver-union-discriminant-bounds

Conversation

@arib06

@arib06 arib06 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What is the purpose of the change

avro_resolver_union_branch (the avro_consume_binary / avro_resolver_new consumer path) read the writer union branch number from the datum and used it directly to index child_resolvers, with no bounds check. read_union in consume-binary.c decodes the discriminant as an int64_t and passes it to a callback typed unsigned int, so a negative or large value becomes a huge index; avro_resolver_union_branch then read child_resolvers[discriminant] past the array and, when that slot was non-NULL, handed the garbage pointer back as an avro_consumer_t * that avro_consume_binary dispatched through. On a two-branch union fed discriminant 100 (bytes C8 01), ASAN reports a heap-buffer-overflow READ of size 8 at resolver.c:1119.

The value decoder already rejects out-of-range discriminants; this older consumer path was missed. The check belongs here because this is the single place that indexes the resolver array with the wire value (the avro_schema_union_branch chokepoint used elsewhere already returns NULL on a miss).

Verifying this change

This change added tests and can be verified as follows:

  • Added test_avro_resolver_union_bounds, which builds a resolver for a ["null","string"] union and feeds avro_consume_binary a datum whose discriminant (100) exceeds the branch count, asserting the read fails instead of crashing. Without the fix the test triggers a heap out-of-bounds read (confirmed under AddressSanitizer); with it the call returns EILSEQ. The full ctest suite passes.

Documentation

  • Does this pull request introduce a new feature? no

avro_resolver_union_branch indexed child_resolvers with the union
branch number taken directly from the datum, so a crafted discriminant
read past the array and could return a wild consumer that
avro_consume_binary then dispatched through. Reject discriminants that
are not below num_children, matching the check the value decoder
already performs.
@github-actions github-actions Bot added the C label Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant