From db7f5ab68f0691ed887224dd64ce7a2b7df91e33 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 10 Dec 2021 11:55:38 +0100 Subject: [PATCH] test: Add BCD unit test --- meson.build | 13 +- src/boot/efi/bcd.c | 27 +++- src/boot/efi/meson.build | 8 + src/boot/efi/test-bcd.c | 162 ++++++++++++++++++++ test/meson.build | 5 + test/test-bcd/.gitattributes | 2 + test/test-bcd/corrupt.bcd.zst | Bin 0 -> 823 bytes test/test-bcd/description-bad-type.bcd.zst | Bin 0 -> 733 bytes test/test-bcd/description-empty.bcd.zst | Bin 0 -> 713 bytes test/test-bcd/description-missing.bcd.zst | Bin 0 -> 703 bytes test/test-bcd/description-too-small.bcd.zst | Bin 0 -> 724 bytes test/test-bcd/displayorder-bad-name.bcd.zst | Bin 0 -> 609 bytes test/test-bcd/displayorder-bad-size.bcd.zst | Bin 0 -> 648 bytes test/test-bcd/displayorder-bad-type.bcd.zst | Bin 0 -> 608 bytes test/test-bcd/empty.bcd.zst | Bin 0 -> 245 bytes test/test-bcd/win10.bcd.zst | Bin 0 -> 743 bytes 16 files changed, 208 insertions(+), 9 deletions(-) create mode 100644 src/boot/efi/test-bcd.c create mode 100644 test/test-bcd/.gitattributes create mode 100644 test/test-bcd/corrupt.bcd.zst create mode 100644 test/test-bcd/description-bad-type.bcd.zst create mode 100644 test/test-bcd/description-empty.bcd.zst create mode 100644 test/test-bcd/description-missing.bcd.zst create mode 100644 test/test-bcd/description-too-small.bcd.zst create mode 100644 test/test-bcd/displayorder-bad-name.bcd.zst create mode 100644 test/test-bcd/displayorder-bad-size.bcd.zst create mode 100644 test/test-bcd/displayorder-bad-type.bcd.zst create mode 100644 test/test-bcd/empty.bcd.zst create mode 100644 test/test-bcd/win10.bcd.zst diff --git a/meson.build b/meson.build index 4c0dd6f8c99..e77c2aa3ac0 100644 --- a/meson.build +++ b/meson.build @@ -1676,8 +1676,14 @@ conf.set10('ENABLE_TIMEDATECTL', get_option('timedated') or get_option('timesync conf.set10('SYSTEMD_SLOW_TESTS_DEFAULT', slow_tests) -##################################################################### +############################################################ +tests = [] +fuzzers = [] + +############################################################ + +# Include these now as they provide gnu-efi detection. subdir('src/fundamental') subdir('src/boot/efi') @@ -1695,7 +1701,7 @@ update_syscall_tables_sh = find_program('tools/update-syscall-tables.sh') xml_helper_py = find_program('tools/xml_helper.py') export_dbus_interfaces_py = find_program('tools/dbus_exporter.py') -##################################################################### +############################################################ config_h = configure_file( output : 'config.h', @@ -1716,9 +1722,6 @@ if dbus_interfaces_dir == '' dbus_interfaces_dir = get_option('datadir') + '/dbus-1' endif -tests = [] -fuzzers = [] - basic_includes = include_directories( 'src/basic', 'src/fundamental', diff --git a/src/boot/efi/bcd.c b/src/boot/efi/bcd.c index 7eabb4da1a5..970c8b1c8ec 100644 --- a/src/boot/efi/bcd.c +++ b/src/boot/efi/bcd.c @@ -1,8 +1,27 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include -#include "macro-fundamental.h" -#include "util.h" +#ifdef SD_BOOT +# include +# include "macro-fundamental.h" +# include "util.h" +# define TEST_STATIC +#else +/* Provide our own "EFI API" if we are running as a unit test. */ +# include +# include +# include +# include "string-util-fundamental.h" + +# define CHAR8 char +# define CHAR16 char16_t +# define UINT8 uint8_t +# define UINT16 uint16_t +# define UINT32 uint32_t +# define UINT64 uint64_t +# define UINTN size_t +# define strncaseeqa(a, b, n) strncaseeq((a), (b), (n)) +# define TEST_STATIC static +#endif enum { SIG_BASE_BLOCK = 1718052210, /* regf */ @@ -206,7 +225,7 @@ static const KeyValue *get_key_value(const UINT8 *bcd, UINT32 bcd_len, const Key * (it always has the GUID 9dea862c-5cdd-4e70-acc1-f32b344d4795). If it contains more than * one GUID, the BCD is multi-boot and we stop looking. Otherwise we take that GUID, look it * up, and return its description property. */ -CHAR16 *get_bcd_title(UINT8 *bcd, UINTN bcd_len) { +TEST_STATIC CHAR16 *get_bcd_title(UINT8 *bcd, UINTN bcd_len) { assert(bcd); if (HIVE_CELL_OFFSET > bcd_len) diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 81e8734452b..a108bf16ab4 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -373,6 +373,14 @@ endforeach ############################################################ +tests += [ + [['src/boot/efi/test-bcd.c'], + [], + [libzstd], + [], + 'HAVE_ZSTD'], +] + test_efi_disk_img = custom_target( 'test-efi-disk.img', input : [efi_stubs[0][0], efi_stubs[1][1]], diff --git a/src/boot/efi/test-bcd.c b/src/boot/efi/test-bcd.c new file mode 100644 index 00000000000..a4d09068a5d --- /dev/null +++ b/src/boot/efi/test-bcd.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "alloc-util.h" +#include "compress.h" +#include "fileio.h" +#include "tests.h" +#include "utf8.h" + +/* Inlcude the implementation directly, so we can poke at some internals. */ +#include "bcd.c" + +static void load_bcd(const char *path, void **ret_bcd, size_t *ret_bcd_len) { + size_t len; + _cleanup_free_ char *fn = NULL, *compressed = NULL; + + assert_se(get_testdata_dir(path, &fn) >= 0); + assert_se(read_full_file_full(AT_FDCWD, fn, UINT64_MAX, SIZE_MAX, 0, NULL, &compressed, &len) >= 0); + assert_se(decompress_blob_zstd(compressed, len, ret_bcd, ret_bcd_len, SIZE_MAX) >= 0); +} + +static void test_get_bcd_title_one( + const char *path, + const char16_t *title_expect, + size_t title_len_expect) { + + size_t len; + _cleanup_free_ void *bcd = NULL; + + log_info("/* %s(%s) */", __func__, path); + + load_bcd(path, &bcd, &len); + + char16_t *title = get_bcd_title(bcd, len); + if (title_expect) { + assert_se(title); + assert_se(memcmp(title, title_expect, title_len_expect) == 0); + } else + assert_se(!title); +} + +TEST(get_bcd_title) { + const char16_t win10[] = { 'W', 'i', 'n', 'd', 'o', 'w', 's', ' ', '1', '0', '\0' }; + test_get_bcd_title_one("test-bcd/win10.bcd.zst", win10, sizeof(win10)); + + test_get_bcd_title_one("test-bcd/description-bad-type.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/description-empty.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/description-missing.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/description-too-small.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/displayorder-bad-name.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/displayorder-bad-size.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/displayorder-bad-type.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/empty.bcd.zst", NULL, 0); +} + +TEST(base_block) { + size_t len; + BaseBlock backup; + uint8_t *bcd_base; + _cleanup_free_ BaseBlock *bcd = NULL; + + load_bcd("test-bcd/win10.bcd.zst", (void **) &bcd, &len); + backup = *bcd; + bcd_base = (uint8_t *) bcd; + + assert_se(get_bcd_title(bcd_base, len)); + + /* Try various "corruptions" of the base block. */ + + assert_se(!get_bcd_title(bcd_base, sizeof(BaseBlock) - 1)); + + bcd->sig = 0; + assert_se(!get_bcd_title(bcd_base, len)); + *bcd = backup; + + bcd->version_minor = 2; + assert_se(!get_bcd_title(bcd_base, len)); + *bcd = backup; + + bcd->version_major = 4; + assert_se(!get_bcd_title(bcd_base, len)); + *bcd = backup; + + bcd->type = 1; + assert_se(!get_bcd_title(bcd_base, len)); + *bcd = backup; + + bcd->primary_seqnum++; + assert_se(!get_bcd_title(bcd_base, len)); + *bcd = backup; +} + +TEST(bad_bcd) { + size_t len; + uint8_t *hbins; + uint32_t offset; + _cleanup_free_ void *bcd = NULL; + + /* This BCD hive has been manipulated to have bad offsets/sizes at various places. */ + load_bcd("test-bcd/corrupt.bcd.zst", &bcd, &len); + + assert_se(len >= HIVE_CELL_OFFSET); + hbins = (uint8_t *) bcd + HIVE_CELL_OFFSET; + len -= HIVE_CELL_OFFSET; + offset = ((BaseBlock *) bcd)->root_cell_offset; + + const Key *root = get_key(hbins, len, offset, "\0"); + assert_se(root); + assert_se(!get_key(hbins, sizeof(Key) - 1, offset, "\0")); + + assert_se(!get_key(hbins, len, offset, "\0BadOffset\0")); + assert_se(!get_key(hbins, len, offset, "\0BadSig\0")); + assert_se(!get_key(hbins, len, offset, "\0BadKeyNameLen\0")); + assert_se(!get_key(hbins, len, offset, "\0SubkeyBadOffset\0Dummy\0")); + assert_se(!get_key(hbins, len, offset, "\0SubkeyBadSig\0Dummy\0")); + assert_se(!get_key(hbins, len, offset, "\0SubkeyBadNEntries\0Dummy\0")); + + assert_se(!get_key_value(hbins, len, root, "Dummy")); + + const Key *kv_bad_offset = get_key(hbins, len, offset, "\0KeyValuesBadOffset\0"); + assert_se(kv_bad_offset); + assert_se(!get_key_value(hbins, len, kv_bad_offset, "Dummy")); + + const Key *kv_bad_n_key_values = get_key(hbins, len, offset, "\0KeyValuesBadNKeyValues\0"); + assert_se(kv_bad_n_key_values); + assert_se(!get_key_value(hbins, len, kv_bad_n_key_values, "Dummy")); + + const Key *kv = get_key(hbins, len, offset, "\0KeyValues\0"); + assert_se(kv); + + assert_se(!get_key_value(hbins, len, kv, "BadOffset")); + assert_se(!get_key_value(hbins, len, kv, "BadSig")); + assert_se(!get_key_value(hbins, len, kv, "BadNameLen")); + assert_se(!get_key_value(hbins, len, kv, "InlineData")); + assert_se(!get_key_value(hbins, len, kv, "BadDataOffset")); + assert_se(!get_key_value(hbins, len, kv, "BadDataSize")); +} + +TEST(argv_bcds) { + for (int i = 1; i < saved_argc; i++) { + size_t len; + _cleanup_free_ void *bcd = NULL; + + assert_se(read_full_file_full( + AT_FDCWD, + saved_argv[i], + UINT64_MAX, + SIZE_MAX, + 0, + NULL, + (char **) &bcd, + &len) >= 0); + + char16_t *title = get_bcd_title(bcd, len); + if (title) { + _cleanup_free_ char *title_utf8 = utf16_to_utf8(title, char16_strlen(title) * 2); + log_info("%s: \"%s\"", saved_argv[i], title_utf8); + } else + log_info("%s: Bad BCD", saved_argv[i]); + } +} + +DEFINE_TEST_MAIN(LOG_INFO); diff --git a/test/meson.build b/test/meson.build index fad40b89464..7d94032d09e 100644 --- a/test/meson.build +++ b/test/meson.build @@ -67,6 +67,11 @@ if install_tests '../-.mount', testsuite08_dir + '/local-fs.target.wants/-.mount') + if conf.get('HAVE_GNU_EFI') == 1 and conf.get('HAVE_ZSTD') == 1 + install_subdir('test-bcd', + exclude_files : '.gitattributes', + install_dir : testdata_dir) + endif if conf.get('ENABLE_RESOLVE') == 1 install_subdir('test-resolve', exclude_files : '.gitattributes', diff --git a/test/test-bcd/.gitattributes b/test/test-bcd/.gitattributes new file mode 100644 index 00000000000..b5f1b48c1ae --- /dev/null +++ b/test/test-bcd/.gitattributes @@ -0,0 +1,2 @@ +*.bcd binary +*.bcd.zst binary diff --git a/test/test-bcd/corrupt.bcd.zst b/test/test-bcd/corrupt.bcd.zst new file mode 100644 index 0000000000000000000000000000000000000000..48b570161cd3a2e24b7c6f5f12b6a06cdf458141 GIT binary patch literal 823 zcmV-71IYX+wJ-f-03S^m05)cLNZ_(KYfyExPlH-bNM>ORQ z&w$r=)Y3+)p85)WIJD@|oFo+-(oojmCGj?1IMp4+f5f!*)6ym~1!DkT0A~QFew3KE z{nOuC*Rx_=|7ojL;l5faio;F$!%2>PQis-md$YqMgHC}v2@74pOXc1XvX0&r*#7JvI@#8=FfA?E^!*jw!2MDR({#FHZUjhH8H%6sWIkZB- z4j-`3&(%-1E(XqbcJ2j_eD_NFzbyO1W2b)fPPk{80=p7k$_HE5|4&Y1h6Ms3COLb+ zMxh5miA4yR5d+&V^4TB6hWvBnPkwfB2b2EiPB8a}1YemIN@b7c!vMako0qfXh&ul8 z0EmXt`#kwP+#xvE*Rg#Uo|YCqU><7C!8 zmWv8IPxZtC+y3^y*dP9}Hsn0a3I*DDXh|oZ_T23j9~00>`|w+t)u7mXqYWBw9m&mJ zRAI+MGqL7{(*l&O>;Hi!+N)QJp1|%S(Sta)Iwe$oVAz5r5V6N^cVy{_4IAn~(JJ@9$oGM|&~H0f3jF!7z>(BOyr&3TX|HMucXJ zH3l>1Reru3$;XqPmtzeJO{q5Q?JJNr90}MDW9#e2MAp zw;jS6uA00l2R47tS5GvN6qJMi3@PEo)5bsJ4TGeB-bHxea?qtaE+PWqU0;6T6reMM z`S?26N7l2UupbQE)ge%siom$Sz+NqAFxxfUFoO!4i+8y&u^M#o82&L}^v)dsyk8)b1GR4O9lzfI z-;3ZN>~_^*bK6}H(%~;3c3`!0i$+GaLGL>|YV8|E!L?IHr%j|x0cQYb0B`{RPvLKn za@QaIYi)f?4EB${UJ*{17b-#KeDI4NIkm8B?Z5uad`6%%>;_s~wOWnDqyJqjtCol0 zo?p-x7#9B`Y$&*3^2|-itO5uDuhEL@kN&;CzWufS*gzrs(8I)E|H{g6!UQuMOfM?Q zDo2D9Vb585%bJT_&E4Ex%hZEjqJ|DztV-=@bpS2#OVxF zqky+{`{>w7VZ(Vg-3p~fRcMAGYIQ=fzFU^$2dd8SGtDyfl_wE}Jk8P4_PG(0v*R}z zwC{H>XQ+WBP$9-fL_|SaSV#xJNW^BVH4+h$SfB}{5FtVo6iF%nic;em3ksDqXL_}Z z98zwUH6runc(V0~-pp?kjo=m?Y?b(CD0vLLp@u(pU4=C|DGDqxy5LYDTx{{?57RwD z{f+>*^1%04Stt49cMV-JmvKNytzK(tA$Bn|@!vkz@MGA9Kx3sFc8cNLAqRNAdO`jF z71PP8^*?adM;X~3v{ubcU?~GSjwmGF-S`J}LS_P;?yKsIKKj^IRPHk*~0^uNjm(!>Bs z2mz;@00#d|E~SJK{8J0(17sx_g|NWx)Lu|LJLY- zJSZe5YUj6q?L(wAWW@bG-E@i4=|6yVT>L!~eg0<-*(_$Oav&%C9ha=h<}&?H$Ho+# z%cq?8iXzlV6;L7KMMOc-Kf>(?*wQ~e{U>e@ndAZg)4}Oq`VT-eT5fK<21C}e|Nfu< z9VZ=xG#Kc8s6qZU+5g8J*x>kR9xSFx-Q$Oz2bD}qb52S{dGOmz%&4kk9X(ei%diVm zRqR491iMcx$*zhd$P&j7=07k=%kau9>2;wLwHV=;Xw<~O(PQG}gNen4kT;{6AKr7T zV;)!4$Gu(G$;-o3cer;rc=xw>IeB+ooE)6B`1m(W&K=Le{?#^w0>4+>&o*;RwbQc0 zHF$q}AR9a=WVY!!9STPkSb|`R{8FwC)oQUiPgTLLEL&mM`Vxq&T8>n9W2k`~lOg6r zBuGJ8P$(S0NW^BVHKHIEv;Y(^Az_3dDUwqD6{W^CD+-jfPwxrg0qxiAm_~4@%ePfx~{Y8mmae{J1)>yIU|8=GOR*Xx* zAds!B%(W0r7#j7TnJavZ>w=)M?p{bi6}pGuaTv(`w>PGHLsR{bTwej$8I(Gk8^96= v4mb)A>tzAzV*0l)#jc$(krzM;`c!gTQCrjqm4`fLhRODSy^TTz*uT~r%sODm literal 0 HcmV?d00001 diff --git a/test/test-bcd/description-missing.bcd.zst b/test/test-bcd/description-missing.bcd.zst new file mode 100644 index 0000000000000000000000000000000000000000..a34ad8a4c102eb224fddb6ac21ce00f8b4463b52 GIT binary patch literal 703 zcmV;w0zmyJwJ-f-03VGN07fQyNAS=#YZwg+(PoS&+7}x*+AJkWTp)ZMjMAYtT-^B=chj{Es!t)LJLw}JuD_? zO2u#g8py3xgv34l`e{?G*M9(~fbsi0^!cAVj*c;3BnA<}?{Nx+ZLRB%8VE#<(a9*D z_lg|c_z1A@ATyGn=qKUm2cV|^iuzF;U1XC>{;%8XZ(1d;&SR0b8^_nGd#S+dBFC^E zEwhnfC&xD0i}h5g{~stvJmqK~F{TUoM~iy?V>;2Bd0I%8liy%8V@mWcS>DwbuDbBv zu)D0%cA)DUyK6xav>t2bFK|h#FtwqjX~|Obf>h#UghNAzj|mwLCl^#i+#%t_XayiD z&lz}{$5V@Y-^t7GtG~ln;rDyUy4>Ck?)rPY`)&sp2e*5(o|*n0&!POSJytXbZ9XZh zYW*S4>HKtq4fKJ8tN~XtU529vg^ebop4S?ykYz_}KT-9SUF!7;U#Nj3lNniLYYICgYZ*NnPLQ^A4`R*Q7z@=dO*{;sy>a zO<%(t+lLk87maC`Ar!PvaCj>h3dFzvn7#%H__@9=G2wUYS~l;@!e_W2eD1Ogqon#b lRQ~v+} literal 0 HcmV?d00001 diff --git a/test/test-bcd/description-too-small.bcd.zst b/test/test-bcd/description-too-small.bcd.zst new file mode 100644 index 0000000000000000000000000000000000000000..76e739369ef3f9a4c03f8a29401dcd50cf686345 GIT binary patch literal 724 zcmV;_0xSI}wJ-f-03S6L0A}cYNbt}$YZz;=89hJP*|7kn>Z>VQ?vQTj)xXSa9bEfjLfuWI<-_@B@KfH(wMD(Eg$R){1!(|l0B``N|G(sS zkaE`_{cAmWl$O{(3WG^7Szzdd7Zbuy`s38buC@RABjj^~&g=(JR%*4{h)e&kWEf9I zESRWR1yy08@gHJHK?RXvXhMW2fEWNP6vhU zz;HOVs30Q_spf?XC;T68|`;JLfHVc#Zn)5UH`{F=lcJjx#YwyY#lA=ig^c*O`nF2iJ4_8 zW=ezSf@DIG1(qPF8n5c~QY88EK9&i3Wl4q}c~`BMS&A`#flHgo)klU4&W&ek>3XIR zxge1^&8P_;-*+;aOZ^$7&vgsHo0{u*xS(ep3{)GP&Gmmwr%J<>*mN6IUQ!glP$a=I z^j6{7@@}XCz3-kZ?|hA4c~_;S&HM&~_W!@k<#%#%@$YbPa`5qRb@+K}?|ZmvaPRN? zIcx7^sDU6;A;&}{NI_viL2}?of|{+?0uhc}U^Sa#!-QBNOqkNV?$z_DSh#v9wa$5O$#E&QKV!*47j-6Pfm(FIoE71gm4 z<@CopM%Umg;~-juM9Z}}9C1balGeG}$I&nYjdj<|0^sV2LoBWc3jFOI(^V>38gA>m zWjbNVkj-tdlySz#knWxYb^g%6=hJ1$$jguHqNxx1RKBgKtQ`TghkE5Xl5|S8=9UuGK zBkc-HVw(s|kUuw)6m`#8VD;b8-1uZ6#Dry%537QRY?%UF07?LH0Po$L1LX6zo*oLc zpB`HU5VV<-EP3mEzTCeXJ6y>4v4Eh09G+Y*XCmtJ;KXhcBsq||W83*@@HJd~Hl&;} zI$5e&fy1Hk@{Rh`-_zf_u>(m%i&N6yU#$b}Csm?!-R=QYA>&7v4)XS+DUeM@^AMYG zk(hVW^iwNcSnx81d&MNvqgB92M9>KXrl*9w2RxMTQcs1vCSekI*X}6)42N(7`EGl( z9h%OAk9^VHBAwvCU?8r$4Y9bqTr-!e6=St(suh{cMzwm;T&mej#-ft3T3|M`nTya5 zpiUef>Kr5_lsMv{zM2kG3=$M7JcxAoI7$%|LIuV%iJc%Jnn9!V5+h@w19Mv`8stv_ zU|nZI67stX0&t&jH2oi1^K~`mN^6sq)drT;C9G=e>Z_|N%i7vm)z{b7+1XaumO{Ai zBA=R0QzYku(#dCK*AizulBXK#SONiu`+dvS^2QO{V zZn^;iaUE#H2>D%%D-#Yf+OU7cgCOAQz}ATmGPcuzG{lX8wXl^FQDHZMp>s0W#{)D# zpfSa=51|K!2r|M9Fnqwr)WFKWHJ*ANc`CsVQCm_8)T#RJvWDu+1+=ulJH-LNNf literal 0 HcmV?d00001 diff --git a/test/test-bcd/displayorder-bad-size.bcd.zst b/test/test-bcd/displayorder-bad-size.bcd.zst new file mode 100644 index 0000000000000000000000000000000000000000..ee89b7709be013fa6f1388c0197d69218606e625 GIT binary patch literal 648 zcmV;30(bo=wJ-f-03X#80LCS8K=8C`GnimP^;}%Mv`8%2`=-Ff5Il{hq;6(SxR~s% z)b|}(rIbHjf9KtIJeu4#g>o5Aw~lMhKY|iwVR!jM`2_^ z2ADl2T!Ju^7?9&a%H8s&FFMBoF#_X8jVkBP(KdWL0YxgW?zwj?CDPp8m@i$o`;#+x z+{U1f+L{dIsmZ<$F$zbCz|jnS(;zDzAYf^VF-k~6k`;j(B6?gB2pxvR9e{iJ&U6!r z%aTC>zw7P(@}D_XeC0ga|10!8vb#_LyILxa4k8SjnIygix?y)iZHS9 zq9;U54vr<(qI9B11tJO}$bf7Z*itkeJpg7F1sVF&OQm&HeT_x^u2y4Vvoc|_t+d`# zR#(^AFYPO<&wskEqOP)3tukXzy|A&~(^u72)YIA7R@zkW7u9Dbca%j#R}rP=0}+u< z3gxK+R4AZq$>(;Fve@i%+0WJ&FuJaau-s;l@svGdQW5Z imYrgNUob~cWwj8srI0}V=#!z%|GM(6>^K1nOZx}pGBM2n literal 0 HcmV?d00001 diff --git a/test/test-bcd/displayorder-bad-type.bcd.zst b/test/test-bcd/displayorder-bad-type.bcd.zst new file mode 100644 index 0000000000000000000000000000000000000000..cc2a8879e7a66a4dd1bdc5f18ee17578287cd844 GIT binary patch literal 608 zcmV-m0-yaTwJ-f-03VeS0EXdbLGW;;IT#K3nOTN-)OBgPiC8@smNYT?4x-idA&6Sx z1FD}p3A+jOfdBE{I$l)MA;t~KMBMDr_zR-GWTi%A%M@7vNdRg9aejK9#=}#g^WmXc z0MX4{Dr6+~D$J&mmKQvj_Ax7aKGVf;UvpS)W zpnxRnXqVIk954egL;#sAkUGl8o4`Byjdj+?OEPB4bGM)TFFZoc<2&u|-3$+@^c+Yn zh8}G-Ar=@HZpLx2*b8RUT9L_WS}vE4Yt3ddmX_?*@>0{yV1j<2REAduQMNc z51PMsT0$^@Y8CQB+v#+=90&nZD6mT8HZBL!7#g}j3YgFckU>O4`JV|3%d`fgONeaQ z(B=X#|2=k_6s>mS21win`C;75`nfC0$natM0|Rs&)_X1KMNec386J5I!}z u3kkx1cT39`!xF~Dy)eX$U$C5~5?hGcT1cSw=-bc+|2pz*XgC2aScno>1}KXF literal 0 HcmV?d00001 diff --git a/test/test-bcd/empty.bcd.zst b/test/test-bcd/empty.bcd.zst new file mode 100644 index 0000000000000000000000000000000000000000..5b3e93849354e8fad4078ff298e01fd64e9699bf GIT binary patch literal 245 zcmVi3W-~>1j zk)^|`N~;*1Kf%_k=px!O1q7!KrwW&c1Qn5y6>++z`qkawGEZH3ZQK4zCX|;DX|urt+P3W^=7T;sIuj`@ouBL@ zT6hza#D?aG#A?wPLBK49H|DS3AK-T-6KO?&q2%}L@Zg976d?RN2uu-nze@dfJWFvgeoQ(RSf#9JkKWhw271{YXEWpasZRxzx4k* z_z}Rk?eF@nWqFqt>)*9np{y?}7lYTT;2+H~?6S7Ce=8I6(ct>I6L3-0YPAiM{#Ui2 zEGR@6W~W@K7n1)BLnIGAma*{=O0f`N1RpOVDBzz(YaCqrmL{=({H*Rkz##X#3mWXg|mqE-^qGiv-1Rke}n9 z3;F*&12GYsM$4sI*BEhOUou&nW2qH&;5i+d6dcD>sFtJ%S$?Owo}UStp%^a=PFo$@i!xkjS&WnEn^btH5e4$CtJMcp< Zm2QdJsz#_gI~ds{LBHO{qym`KVb`PYfUN)k literal 0 HcmV?d00001