From 4d980b1fecb6bb8b47dae3ceab9b1b57fbf29394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= Date: Thu, 12 Jun 2025 17:56:17 +0200 Subject: [PATCH] Correcting a UBSan error in builder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a table with optional fields is created before the ds-stack is allocated we get an UBSan error. The ds stack would normally be allocated when a field is added to the table. /xxxx/flatcc/src/runtime/builder.c:613:16: runtime error: null pointer passed as argument 1, which is declared to never be null /usr/include/string.h:61:62: note: nonnull attribute specified here #0 0x600c6b6e in exit_frame /xxxx/flatcc/src/runtime/builder.c:613:9 #1 0x600d4520 in flatcc_builder_end_table /xxxx/flatcc/src/runtime/builder.c:1380:5 #2 0x600a0be8 in optional_scalars_NestedTable_end /xxxx/flatcc/build/Debug/test/optional_scalars_test/generated/optional_scalars_test_builder.h:35:1 #3 0x600a08a7 in create_scalar_stuff /xxxx/flatcc/test/optional_scalars_test/optional_scalars_test.c:27:20 #4 0x600ab4f5 in test /xxxx/flatcc/test/optional_scalars_test/optional_scalars_test.c:176:5 #5 0x600abd1f in main /xxxx/flatcc/test/optional_scalars_test/optional_scalars_test.c:272:9 #6 0xe9186518 (/lib/i386-linux-gnu/libc.so.6+0x21518) (BuildId: 6f8a2d2f90a25e7865aa6fdfd9a7825d62d53f51) #7 0xe91865f2 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x215f2) (BuildId: 6f8a2d2f90a25e7865aa6fdfd9a7825d62d53f51) #8 0x6007053a in _start (/xxxx/flatcc/build/Debug/test/optional_scalars_test/optional_scalars_test_d+0x2653a) (BuildId: d47f8a02ee936bc1bc53a0efd6ad360faa6428d7) SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /xxxx/flatcc/src/runtime/builder.c:613:16 Signed-off-by: Björn Svensson --- src/runtime/builder.c | 5 ++++- test/optional_scalars_test/optional_scalars_test.c | 9 ++++++++- test/optional_scalars_test/optional_scalars_test.fbs | 6 ++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/runtime/builder.c b/src/runtime/builder.c index c4d159d68..98e68b423 100644 --- a/src/runtime/builder.c +++ b/src/runtime/builder.c @@ -608,7 +608,10 @@ static int enter_frame(flatcc_builder_t *B, uint16_t align) static inline void exit_frame(flatcc_builder_t *B) { - memset(B->ds, 0, B->ds_offset); + /* Clear the ds stack (if any struct frames have been allocated). */ + if (B->ds) { + memset(B->ds, 0, B->ds_offset); + } B->ds_offset = frame(ds_offset); B->ds_first = frame(ds_first); refresh_ds(B, frame(type_limit)); diff --git a/test/optional_scalars_test/optional_scalars_test.c b/test/optional_scalars_test/optional_scalars_test.c index 7566c056c..391372a2a 100644 --- a/test/optional_scalars_test/optional_scalars_test.c +++ b/test/optional_scalars_test/optional_scalars_test.c @@ -21,6 +21,11 @@ int create_scalar_stuff(flatcc_builder_t *builder) { ns(ScalarStuff_start_as_root(builder)); + /* Test of creating a table before any fields are added. */ + ns(NestedTable_ref_t) nested_table; + ns(NestedTable_start(builder)); + nested_table = ns(NestedTable_end(builder)); + ns(ScalarStuff_just_i8_add(builder, 10)); ns(ScalarStuff_maybe_i8_add(builder, 11)); ns(ScalarStuff_default_i8_add(builder, 12)); @@ -49,6 +54,8 @@ int create_scalar_stuff(flatcc_builder_t *builder) ns(ScalarStuff_maybe_xfactor_add)(builder, ns(OptionalFactor_Twice)); ns(ScalarStuff_default_xfactor_add)(builder, ns(OptionalFactor_Twice)); + ns(ScalarStuff_nested_table_add)(builder,nested_table); + ns(ScalarStuff_end_as_root(builder)); return 0; @@ -176,7 +183,7 @@ int test(void) } const char *expected_json = -"{\"just_i8\":10,\"maybe_i8\":11,\"default_i8\":12,\"just_i16\":42,\"maybe_i16\":42,\"maybe_u32\":0,\"default_u32\":0,\"just_f32\":42,\"maybe_f32\":42,\"just_bool\":true,\"maybe_bool\":true,\"just_enum\":\"One\",\"maybe_enum\":\"One\",\"just_xfactor\":\"Twice\",\"maybe_xfactor\":\"Twice\"}"; +"{\"just_i8\":10,\"maybe_i8\":11,\"default_i8\":12,\"just_i16\":42,\"maybe_i16\":42,\"maybe_u32\":0,\"default_u32\":0,\"just_f32\":42,\"maybe_f32\":42,\"just_bool\":true,\"maybe_bool\":true,\"just_enum\":\"One\",\"maybe_enum\":\"One\",\"just_xfactor\":\"Twice\",\"maybe_xfactor\":\"Twice\",\"nested_table\":{}}"; #if 0 int print_buffer(const void *buf, size_t size) diff --git a/test/optional_scalars_test/optional_scalars_test.fbs b/test/optional_scalars_test/optional_scalars_test.fbs index ba4c9d4c1..6a3cdd850 100644 --- a/test/optional_scalars_test/optional_scalars_test.fbs +++ b/test/optional_scalars_test/optional_scalars_test.fbs @@ -68,4 +68,10 @@ table ScalarStuff { maybe_yfactor: OptionalFactor = null; default_yfactor: OptionalFactor = Twice; + nested_table: NestedTable; +} + +table NestedTable { + u64_0: uint64 = null; + u64_1: uint64 = null; }