Skip to content

Reject union values that are missing when the union type is set - #9441

Open
vivek7424 wants to merge 1 commit into
google:masterfrom
vivek7424:fix-union-value-without-value
Open

vivek7424 wants to merge 1 commit into
google:masterfrom
vivek7424:fix-union-value-without-value

Conversation

@vivek7424

Copy link
Copy Markdown

Fixes #9416.

Problem

A table with a union field whose type is set but whose value is absent passes VerifyBuffer. The generated union verify case calls verifier.VerifyTable(ptr), and VerifyTable accepts a null pointer. The generated object API then dereferences that null pointer when the buffer is unpacked and packed again.

Reproduced locally on the unpatched tree with clang on Linux: VerifyMonsterBuffer returns true, and the object-API round trip ends in a SIGSEGV in Monster::Pack with _o == nullptr. An AddressSanitizer/UBSan build reports the same null member access at the same generated line.

Change

  • src/idl_gen_cpp.cpp: for union members that are tables, the generator now emits return ptr && verifier.VerifyTable(ptr);.
  • 11 checked-in generated headers were regenerated with the patched flatc using scripts/generate_code.py. Every changed line is the union verify line; no other line changed.
  • tests/union_underlying_type_test_generated.h has the same one-line change applied by hand. I could not identify the command that generates this file (it is not in scripts/generate_code.py), so please check it against the generator if you have that command.
  • tests/test.cpp: new UnionTypeWithoutValueRejectedTest. It checks that a union type with no value is rejected, and that a union with a value, and a union of type NONE, still verify.

Verification

  • Patched tree: the full flattests suite passes (build exit 0, run exit 0).
  • Unpatched generator and headers, with the same test.cpp: the new test fails at test.cpp (the check that the union-without-value buffer is rejected).

Scope and limits

  • Only table union members are changed. Other union member kinds (strings, structs) were not analyzed in this change.
  • No change to the verifier code in include/flatbuffers/verifier.h; VerifyTable still accepts null for optional fields.

A table with a union field whose type is set but whose value is absent passed
VerifyBuffer. The generated union verify case called verifier.VerifyTable(ptr),
which accepts a null pointer, and the object API then dereferenced that null
pointer when the buffer was packed again.

Check the table pointer for table union members, regenerate the affected
checked-in headers, and add a regression test.

Fixes google#9416
@github-actions github-actions Bot added c++ codegen Involving generating code from schema labels Oct 28, 2026
@vivek7424

Copy link
Copy Markdown
Author

Issue #9416 is also addressed by #9417, which adds a null guard at the start of the generated Pack functions (if (!value) { return 0; }). This PR changes the generated Verify functions so that a union whose type is set but whose value is missing is rejected during verification (return ptr && verifier.VerifyTable(ptr);). The two changes do not conflict in intent: the verifier change rejects the malformed buffer, and the Pack guard protects callers of Pack(). We are happy to rebase onto whichever approach the maintainers prefer, or to combine them. Please let us know which you would like to keep.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ codegen Involving generating code from schema

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[C++] Object API: Pack() dereferences null when a union has its type set but no value (buffer passes the verifier)

1 participant