From 160e8f2fdc9d5989e652709fae3fac0bd9aaed14 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 29 Oct 2018 17:40:19 -0700 Subject: [PATCH] Disallowed 0 byte structs. This is because they are incompatible with C++ and possibly other languages that make them minimum size 1 (to make sure multiple such objects don't reside at the same address). Forcing them to size 1 was also not practical, as that is requires updating the logic of a lot of implementations and thus possibly backwards incompatible. More here: https://github.com/google/flatbuffers/issues/4122 Change-Id: I2bfdc8597b7cfd2235bb4074bb2ae06f81f8e57d --- ...nster_test_my_game.example2_generated.dart | 2 +- ...onster_test_my_game.example_generated.dart | 2 +- src/idl_parser.cpp | 25 ++++++++++-------- tests/include_test/sub/include_test2.fbs | 2 +- tests/javatest.bin | Bin 512 -> 512 bytes tests/monster_test.bfbs | Bin 6352 -> 6376 bytes tests/monster_test.schema.json | 1 + tests/test.cpp | 1 + 8 files changed, 19 insertions(+), 14 deletions(-) diff --git a/dart/test/monster_test_my_game.example2_generated.dart b/dart/test/monster_test_my_game.example2_generated.dart index 11e51ab29..9a3ab6626 100644 --- a/dart/test/monster_test_my_game.example2_generated.dart +++ b/dart/test/monster_test_my_game.example2_generated.dart @@ -8,8 +8,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb; import 'include_test1_my_game.example2_generated.dart'; import 'include_test2_my_game.example2_generated.dart'; -import './monster_test_my_game.example_generated.dart' as my_game_example; import './monster_test_my_game_generated.dart' as my_game; +import './monster_test_my_game.example_generated.dart' as my_game_example; class Monster { Monster._(this._bc, this._bcOffset); diff --git a/dart/test/monster_test_my_game.example_generated.dart b/dart/test/monster_test_my_game.example_generated.dart index 5adb4f239..d243b2d48 100644 --- a/dart/test/monster_test_my_game.example_generated.dart +++ b/dart/test/monster_test_my_game.example_generated.dart @@ -8,8 +8,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb; import 'include_test1_my_game.example_generated.dart'; import 'include_test2_my_game.example_generated.dart'; -import './monster_test_my_game.example2_generated.dart' as my_game_example2; import './monster_test_my_game_generated.dart' as my_game; +import './monster_test_my_game.example2_generated.dart' as my_game_example2; class Color { final int value; diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 0eec35351..c4f7c8660 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -1778,21 +1778,24 @@ CheckedError Parser::ParseDecl() { EXPECT('{'); while (token_ != '}') ECHECK(ParseField(*struct_def)); auto force_align = struct_def->attributes.Lookup("force_align"); - if (fixed && force_align) { - auto align = static_cast(atoi(force_align->constant.c_str())); - if (force_align->type.base_type != BASE_TYPE_INT || - align < struct_def->minalign || align > FLATBUFFERS_MAX_ALIGNMENT || - align & (align - 1)) - return Error( - "force_align must be a power of two integer ranging from the" - "struct\'s natural alignment to " + - NumToString(FLATBUFFERS_MAX_ALIGNMENT)); - struct_def->minalign = align; + if (fixed) { + if (force_align) { + auto align = static_cast(atoi(force_align->constant.c_str())); + if (force_align->type.base_type != BASE_TYPE_INT || + align < struct_def->minalign || align > FLATBUFFERS_MAX_ALIGNMENT || + align & (align - 1)) + return Error( + "force_align must be a power of two integer ranging from the" + "struct\'s natural alignment to " + + NumToString(FLATBUFFERS_MAX_ALIGNMENT)); + struct_def->minalign = align; + } + if (!struct_def->bytesize) return Error("size 0 structs not allowed"); } struct_def->PadLastField(struct_def->minalign); // Check if this is a table that has manual id assignments auto &fields = struct_def->fields.vec; - if (!struct_def->fixed && fields.size()) { + if (!fixed && fields.size()) { size_t num_id_fields = 0; for (auto it = fields.begin(); it != fields.end(); ++it) { if ((*it)->attributes.Lookup("id")) num_id_fields++; diff --git a/tests/include_test/sub/include_test2.fbs b/tests/include_test/sub/include_test2.fbs index 3257ffc14..7225735cb 100644 --- a/tests/include_test/sub/include_test2.fbs +++ b/tests/include_test/sub/include_test2.fbs @@ -5,7 +5,7 @@ namespace MyGame.OtherNameSpace; enum FromInclude:long { IncludeVal } -struct Unused {} +struct Unused { a:int; } table TableB { a:TableA; diff --git a/tests/javatest.bin b/tests/javatest.bin index 77835c736b37d60fcf336052a491c9526fd5112e..15bea5fb882a90771c86ca71abbe5028fa6811c6 100644 GIT binary patch delta 85 zcmZo*X<%VtVPIgK$g;=9gn@y<*WWJ~NHJ(IgfQp;X)Oj7AgKVv@(dCTA`AiyK-FNt W4KGU{Km;0q6yszT#y^$f3V}mo^{hssu&pH41>|Onr`kU=F z6G0&wDQ3!qnD7g6E+oVwiuMX2eo#z=hSGHaJ$MHypbDQs3`X%Yv}xKj)@eyNgy*%h zkQ@H0xdFy-zU(mE$Ah+0(27rOwUEXSwrwzgU=JI~ndN06#0CnH!yQD@int}2!ejQZ zIiQFxi8+fId!><6$R*Kkyhqoj6md$@g>Q(M-&nd_k}S><*{z5}l0n?$2pe6B*d-aq zgO0G7Rm3Jq&v#7uE4+IsTT${ui2U#^M+6{=L*)s$iu2_$BQ?vVxWm_2?@VZV9($cT zjj@sg8s6C^FF0GslqOfqy#8bTn&T(-xSFM^D`t(%@qvfuqmtCVD-Pt3z6Eu!wL zv=$ZeuoomhfK9#&=D4D4M`aO5ea-US_##cMi>$zlH@dXE48p-HFFOlR$SHffPm7Z( zkKOCUBmS^?TM>g2L|qYk{YmJ+m;R`x7x9z7)l3yxncbZ(Vnd(ERGQBl<+qwW%}sIS?`G6y-nR1GIu+qf-%HoVU0)7_RRtA#wznyxP9>@FK$>P^yb+#hO$qj)BiFveDn>8@~KchK+brl;>jhnGT^0k?;$T#ZEJ5H_5v U*o?W2x>J_hLV+(r2|K@m|Bkm{I{*Lx delta 1197 zcmYk5TSydP6vw|a>)vLa*`2+)xzK`JNv^oMWm|?Tx}eZyDIWucd9Ci$pGc!54o<${ zX>(BTltkqum%&bRq1G>voueXrLTMi*v2k(?KM+}v#L7tr&J!v8BZ^r#d4RhtL9I>_ zGbiI%YYFPDlH_rc$Y9D-;5y7$pQPjmV{eD=Swa9Y9JD4OjZ4<37MmBsqQfDquqBn{ zc}&|%w1FKDXn0!#Pq5X%C|25|ddI?c+QI^M*b`jU9yPjTnp4b2C8>RT9LOK_08C<& z8U-D1s}ZQe*J=%PVpfd<)pdlF=0$9D#FV~8>~W;DsYOvhc-ewK9dV$s^CMd0(sp6; zm`JZAqM(Ymh>S}j46Va=L~@b{L#ZZ_*z&dx)z>0gt0Y2a7S9vumqh5$t0MAU5}`x8 zpoKMcMd&Ep-d?opVPitpatg<}=~%5FRdOrXsqZ$bq<|B6JY6ODLVpG{h%*kR-{FSdz&s zs_sJLeO4f+n1SS5u+n`+ACrM%4SwZt%$?xx#vQ8Mw<^NL;ytB%U>33RyfZHyK4toB z8%xQ!&9y%13F>J{Gzws;HB5Wz>9c#|2`iaZobuG^u{EJA+*Q{x=4}KEc6&ocy-ak9 zMW*CKI6`z&?*G*1aM~Nv-0MO_e1v^y_<~xMBw}&K@Q5#1(XxX)qI({^)js#|DxIDk zF+?ycj4JqtYMt4+y1Gm;e9( diff --git a/tests/monster_test.schema.json b/tests/monster_test.schema.json index 09c716c05..b2df316aa 100644 --- a/tests/monster_test.schema.json +++ b/tests/monster_test.schema.json @@ -16,6 +16,7 @@ "MyGame_OtherNameSpace_Unused" : { "type" : "object", "properties" : { + "a" : { "type" : "number" } }, "additionalProperties" : false }, diff --git a/tests/test.cpp b/tests/test.cpp index 90c791736..d59160be0 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -1230,6 +1230,7 @@ void ErrorTest() { TestError("enum X:byte (bit_flags) { Y=8 }", "bit flag out"); TestError("table X { Y:int; } table X {", "datatype already"); TestError("struct X (force_align: 7) { Y:int; }", "force_align"); + TestError("struct X {}", "size 0"); TestError("{}", "no root"); TestError("table X { Y:byte; } root_type X; { Y:1 } { Y:1 }", "end of file"); TestError("table X { Y:byte; } root_type X; { Y:1 } table Y{ Z:int }",