. "$BST_LIB" # BST-TIMEOUT: 300 # one probe run with six forked fixtures inside it, three # of them bounded at 20s, plus ~120 shell extractions; the # 60s default is for suites that fork far less than this. # libfakekey 0.3+git (SRCREV 7ad88591) -- UTF-8 characters to synthetic X key # presses, through the XTEST extension. poky meta/recipes-graphics/libfakekey. # See libfakekey_%.bbappend for what the port had to repair and why. # # --------------------------------------------------------------------------- # THIS SUITE CAN RUN THE LIBRARY'S DOCUMENTED NO-SERVER PATH FOR REAL, WHICH # MOST X CLIENT-LIBRARY PORTS ON THIS ARM CANNOT # # libfakekey is seven entry points, and six of them end in a request on a wire. # THIS IMAGE HAS NO X SERVER. For libXv and libXvMC that ended the discussion: # their Display-taking entry points fall through Xlib's own prologue, which # loads through the pointer, so an invented Display makes a probe report its own # mistake rather than a finding. Sections 6, 7 and 9 of this suite are what is # different here, and the difference is real code rather than a loophole: # # * fakekey_init's FIRST statement is `if (xdpy == NULL) return NULL;' # (libfakekey.c:141), and NULL is exactly what a caller on this image is # holding -- XOpenDisplay returns it with no server. So section 6 runs the # documented refusal end to end, on the real inputs, out of libfakekey.a. # # * fakekey_press VALIDATES BEFORE IT CONNECTS. It reads fk->held_keycode, # calls utf8_to_ucs4, and on a decode failure returns 0 at libfakekey.c:429 # having touched nothing else in the handle. Section 7 walks that boundary # from the reject side with a zeroed handle -- every rejecting input, and # deliberately no accepting one, because an accepted character falls through # to XKeysymToKeycode(fk->xdpy, ...) and fk->xdpy is NULL. # # * fakekey_release and fakekey_repeat both open `if (!fk->held_keycode) # return;', so on an idle handle they are complete, side-effect-free # executions. Also section 7. # # --------------------------------------------------------------------------- # THE ARITHMETIC IS WHERE THIS PORT IS MOST AT RISK, AND SECTION 4 IS IT # # The remapping path -- the reason the ticket calls this the round's # keyboard-mapping member -- indexes the KeySym table it is about to hand to # XChangeKeyboardMapping with # # index = (max_keycode - min_keycode - modifiedkey - 1) * n_keysyms_per_keycode # libfakekey.c:319 # # every term of which lives in struct FakeKey. That structure holds a Display* # and a KeySym*, and a KeySym is an `unsigned long'. On wasm32 all three are # 4 bytes where the build host has 8, so the structure is 48 bytes here against # 64 there and every member offset below it moves. A packing difference would # corrupt every mapping change the library makes, silently. # # WHY SECTION 4 ASSERTS A COPY OF A PRIVATE STRUCTURE. struct FakeKey is # OPAQUE: fakekey.h publishes `typedef struct FakeKey FakeKey;' and nothing # else, so the "sizeof and member offsets of the public structures the header # defines" the ticket asks for has no public structure to stand on -- the header # defines exactly one type, the FakeKeyModifier enum, and section 5 pins it. # The probe declares a byte-for-byte copy of the definition at # src/libfakekey.c:44-55 instead, and do_compile GREPS THE REAL SOURCE AND # REFUSES THE BUILD if the two have drifted. So these are not assertions about # a structure somebody typed out once: they are the same declaration, compiled # by the same compiler that compiled the library, with the copy kept honest # mechanically. # # --------------------------------------------------------------------------- # WHERE THE NUMBERS COME FROM # # Everything below was MEASURED on 2026-09-12, not predicted: # # * the arch-independent values (sections 5, 7, 9, 10) by running this same # probe against a native build of the same SRCREV on x86-64; # * the ILP32 values (section 4) by compiling the same structure from the same # headers with `gcc -m32 -c' under _Static_assert, so each one is confirmed # by the compiler rather than derived by hand; # * the packaging (section 1) read out of the .deb files this recipe built. # # A DIFF AGAINST THE x86-64 REFERENCE WOULD MAKE AGREEMENT THE DEFECT for # section 4, which is why those expectations are written out rather than # compared: the whole content of those cases is that a pointer and a KeySym are # four bytes here and eight there. # # WHAT IS NOT MEASURED, AND SAYS SO: whether any of this EXECUTES on wasm32. # Phase A of a batched pass runs no image. Section 3 is the case that answers # it, and sections 4 through 9 are readable only if it is green. # # --------------------------------------------------------------------------- # READ A RED IN SECTION ORDER; THE FIRST SECTION TO GO RED LOCALISES THE DEFECT # # 1 the payload arrived packaging only # 2 the .pc resolves consumers find and LINK the library # 3 the probe runs to its end libfakekey.a executes on this arm # 4 the client ABI the arch-sensitive layout # 5 the header's constants the flag set and the X indices # 6 the display that is not there the documented no-server path, run # 7 the UTF-8 reject boundary real decoder execution, real returns # 8 a NULL handle containment only -- see the section # 9 the entry-point census every client API, out of the archive # # 3 green with 4 red is a word-size fault in the toolchain rather than anything # wrong with this recipe. 4 green with 6 or 7 red is the layout right and the # library's own code over it wrong, which is the most consequential thing this # port could get wrong. 2 red with everything else green means the port builds # and the next package to consume it will not link. # --------------------------------------------------------------------------- # A root prefix, empty on the target and set only when this suite is validated # NATIVELY under dash before it ships. The runner never sets it, so on the image # every path below is exactly the absolute one. R="${BST_LIBFAKEKEY_ROOT:-}" INC=$R/usr/include/fakekey LIB=$R/usr/lib PCD=$R/usr/lib/pkgconfig FT=$R/usr/libexec/libfakekey-tests work=${TMPDIR:-/tmp}/bst-libfakekey.$$ rm -rf "$work"; mkdir -p "$work" hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "missing or empty: $2"; fi } # fk_line # # The prefix is matched with grep -F rather than the whole line, so a red reports # WHAT THE PROBE ACTUALLY SAID for that case instead of merely "absent". Every # prefix is unique by construction: each is a section tag plus a case name, and # the case name is followed by a space that ends it. fk_line() { _l=$(grep -F -- "$2" "$work/out" 2>/dev/null | head -1) check_eq "$1" "$2$3" "$_l" } # --------------------------------------------------------------------------- # 0. THE CANARY, which is not an assertion about libfakekey at all. # # The guest console drops a suite's FIRST BST result line before the host parser # sees it -- brintos/linux#96. The harness computes its pass count as # total-minus-failures, so THE DROPPED LINE IS COUNTED AS A PASS, and a suite # whose first case is a genuine `not ok' loses the one line that mattered. So # the first line out of this file asserts something already true. # Remove this case when #96 is fixed. bst_ok libfakekey/suite-canary # --------------------------------------------------------------------------- # 1. THE PAYLOAD. check_rc libfakekey/dir-include 0 test -d "$INC" # libfakekey ships exactly ONE header, and unlike the xorg-lib ports its # directory is its OWN (${includedir}/fakekey, from fakekey/Makefile.am), not # the shared X11/extensions. So a count here is stable and worth taking: it says # the install is this recipe's whole install. hasfile libfakekey/hdr-fakekey "$INC/fakekey.h" check_eq libfakekey/hdr-count 1 \ "$(ls "$INC" 2>/dev/null | wc -l | tr -d ' ')" # The client API, by name, out of the installed header -- asserted on contents # rather than on size, because a truncated install would still be non-empty and # these seven names are what every consumer's translation unit refers to. for f in fakekey_init fakekey_press fakekey_press_keysym fakekey_repeat \ fakekey_release fakekey_reload_keysyms fakekey_send_keyevent; do check libfakekey/hdr-decl-$f grep -q "$f" "$INC/fakekey.h" done # THE HANDLE IS OPAQUE, AND THAT IS AN ASSERTION RATHER THAN AN OBSERVATION. # fakekey.h publishes `typedef struct FakeKey FakeKey;' and never the body. It # is why section 4 asserts a checked copy, and an upstream that started # publishing the layout would silently make this whole image's consumers # ABI-coupled to it -- so pin the absence. check libfakekey/hdr-handle-typedef \ grep -q 'typedef struct FakeKey FakeKey;' "$INC/fakekey.h" check_rc libfakekey/hdr-handle-opaque 1 \ grep -q '^struct FakeKey$' "$INC/fakekey.h" # THE PACKAGE VERSION IS NOT IN THE HEADER, AND THAT IS NOT AN OMISSION. # fakekey.h defines no version macro at all. The version is asserted through # pkg-config (section 2) and through the probe, compiled with -DLIBFAKEKEY_PV # out of the recipe's own ${PV} (section 3), so a stale probe left by an earlier # build cannot pass for this one. This case pins the absence, so a future # upstream that starts defining one is noticed rather than silently unasserted. check_rc libfakekey/hdr-no-package-version 1 \ grep -q 'FAKEKEY_VERSION\|LIBFAKEKEY_VERSION' "$INC/fakekey.h" # The delivery. bst_lib_shape rather than an assertion that no .so exists: # BRINTOS-1740 retires the static-only premise one recipe at a time, so what # survives conversion is that whatever IS shipped is usable. hasfile libfakekey/archive "$LIB/libfakekey.a" bst_lib_shape libfakekey/lib-shape "$LIB/libfakekey.so*" hasfile libfakekey/probe-shipped "$FT/libfakekey-probe" check_rc libfakekey/probe-executable 0 test -x "$FT/libfakekey-probe" # --------------------------------------------------------------------------- # 1b. THE PACKAGES, through dpkg's own file lists. # # A file that reached the image by some other route satisfies the stat above and # does not satisfy the claim that this recipe PACKAGED it. There is no bare # `libfakekey' package on this arm: FILES:${PN} is ${libdir}/libfakekey.so.*, # which a static-only build never produces, so the three below are the whole of # what ships and -tests deliberately takes no RDEPENDS on a package that does # not exist. nl=' ' hasline() { case "$nl$3$nl" in *"$nl$2$nl"*) bst_ok "$1" ;; *) bst_notok "$1" "not listed: $2" ;; esac; } if [ -d "$R/var/lib/dpkg/info" ]; then bst_ok libfakekey/dpkg-db-present devlist=$(cat "$R/var/lib/dpkg/info/libfakekey-dev.list" 2>/dev/null) if [ -n "$devlist" ]; then bst_ok libfakekey/pkg-dev-list hasline libfakekey/pkg-dev-header /usr/include/fakekey/fakekey.h "$devlist" hasline libfakekey/pkg-dev-pc /usr/lib/pkgconfig/libfakekey.pc "$devlist" else bst_notok libfakekey/pkg-dev-list "no libfakekey-dev.list -- the -dev packaging cases cannot run" fi # The archive is -staticdev's, not -dev's, and that split is the packaging # claim worth asserting: a consumer that installed only -dev would compile and # fail to link. stlist=$(cat "$R/var/lib/dpkg/info/libfakekey-staticdev.list" 2>/dev/null) if [ -n "$stlist" ]; then bst_ok libfakekey/pkg-staticdev-list hasline libfakekey/pkg-staticdev-archive /usr/lib/libfakekey.a "$stlist" else bst_notok libfakekey/pkg-staticdev-list "no libfakekey-staticdev.list" fi tstlist=$(cat "$R/var/lib/dpkg/info/libfakekey-tests.list" 2>/dev/null) if [ -n "$tstlist" ]; then bst_ok libfakekey/pkg-tests-list hasline libfakekey/pkg-tests-probe \ /usr/libexec/libfakekey-tests/libfakekey-probe "$tstlist" else bst_notok libfakekey/pkg-tests-list "no libfakekey-tests.list" fi else bst_skip libfakekey/dpkg-db-present "no dpkg database on this image" fi # --------------------------------------------------------------------------- # 2. THE .pc -- how a consumer finds the header AND SUCCEEDS AT LINKING. # # This section is not boilerplate for this port. Upstream's Libs named # -lfakekey LAST, behind the X archives it needs, which is invisible on a shared # distro and fatal on this one -- an archive is searched once, when the linker # reaches it. The port patches the order, and pc-libs-order below is the case # that proves the patch is in the artifact rather than only in the tree. hasfile libfakekey/pc-present "$PCD/libfakekey.pc" check libfakekey/pc-libs-name grep -q '\-lfakekey' "$PCD/libfakekey.pc" # The ORDER, read straight out of the file: -lfakekey must come before the first # X archive on the Libs line. Written as a positional test rather than an exact # string so that it stays true when the closure's membership changes. pclibs=$(grep '^Libs:' "$PCD/libfakekey.pc" 2>/dev/null) case "$pclibs" in *-lfakekey*-lX11*) bst_ok libfakekey/pc-libs-order ;; *) bst_notok libfakekey/pc-libs-order \ "-lfakekey does not precede -lX11 on: $pclibs" ;; esac # The closure the port put there, by name. Each of these is an archive # libfakekey.a or its dependencies leave undefined on this arm; a .pc missing # one is the phantom-import refusal moved to the next consumer. for l in Xtst Xext X11 xcb Xau Xdmcp; do check libfakekey/pc-libs-has-$l grep -q -- "-l$l" "$PCD/libfakekey.pc" done # AND NO BUILD-HOST PATH IN IT. FAKEKEY_LIBS is substituted into this file, so a # -L pointing at a recipe-sysroot would ship to the target and be handed to # every consumer. The bbappend omits it deliberately; this is the case that # keeps it omitted. check_rc libfakekey/pc-no-staging-path 1 \ grep -q 'recipe-sysroot\|/tmp-glibc/\|/work/' "$PCD/libfakekey.pc" if command -v pkg-config >/dev/null 2>&1; then bst_ok libfakekey/pkg-config-present check libfakekey/pc-exists pkg-config --exists libfakekey check libfakekey/pc-validate pkg-config --validate libfakekey # THE .pc VERSION IS 0.3 AND THE RECIPE'S PV IS 0.3+git, AND THEY DO NOT # AGREE AS LITERALS. # # The ticket asks for the modversion and the pinned version "asserted to agree # as literals". They do not, and asserting that they did would be asserting a # thing that is false: configure.ac:2 is AC_INIT([libfakekey], 0.3), so # @VERSION@ -- and therefore the installed .pc -- is 0.3, while the recipe # sets PV = "0.3+git" because it builds from a git revision with no release # tarball behind it. What is assertable, and is the real invariant, is each # literal on its own plus the DOCUMENTED RELATION between them: PV is the .pc # version with the +git suffix that says where the source came from. Both # cases here, and probe-pv in section 3, would go red on a version bump -- # which is the point. # # The PV half is asserted in SECTION 3, not here: it is read out of the # probe's transcript, and the probe has not run yet at this point in the file. check_eq libfakekey/pc-modversion 0.3 \ "$(pkg-config --modversion libfakekey 2>/dev/null)" check_eq libfakekey/version-relation "0.3+git" \ "$(pkg-config --modversion libfakekey 2>/dev/null)+git" # PKG_CONFIG_ALLOW_SYSTEM_LIBS is required for the same reason 57-xtrans.test # records for its --cflags case: pkg-config SUPPRESSES a -L naming a directory # already on the linker's default path, so the bare query answers usefully # only for the -l part. check_out libfakekey/pc-libs -lfakekey \ env PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs libfakekey check_out libfakekey/pc-libs-pulls-xtst -lXtst \ env PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs libfakekey check_out libfakekey/pc-libs-pulls-xcb -lxcb \ env PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs libfakekey check_out libfakekey/pc-cflags -I \ env PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 pkg-config --cflags libfakekey else bst_skip libfakekey/pkg-config-present "pkg-config not installed on this image" fi # --------------------------------------------------------------------------- # 3. THE PROBE RAN. # # Everything from section 4 on is read out of this transcript, so this case is # the one that says whether the rest are about libfakekey or about a probe that # died. bst_probe bounds it and, on an overrun, reports the LAST LINE the probe # printed -- which names the call it stopped at. bst_probe libfakekey/probe-ran "$work/out" 180 "$FT/libfakekey-probe" probe_rc=$? if [ "$probe_rc" -ne 0 ]; then bst_skip libfakekey/probe-transcript \ "the probe did not complete (rc=$probe_rc); sections 4-9 would report its absence, not this library's behaviour" else bst_ok libfakekey/probe-transcript # The terminator. A probe killed part-way leaves a transcript whose earlier # lines all match, so every case below would go green over a truncated run. fk_line libfakekey/probe-end "fkp/end " "reached" # The recipe's own ${PV}, compiled into the probe with -DLIBFAKEKEY_PV, so a # stale probe left by an earlier build cannot pass for this one. The other # half of the version pair is pc-modversion in section 2, and they are # deliberately different literals -- see the note there. fk_line libfakekey/probe-pv "fkp/pv " "0.3+git" # ------------------------------------------------------------------------- # 4. THE CLIENT ABI -- ILP32, and every value confirmed by `gcc -m32 -c' # under _Static_assert on 2026-09-12. The x86-64 reference is given beside # each pair only where it differs, because a reader's first question is # whether the number is a target fact or a typo. # 48 here; 64 on the LP64 reference build. fk_line libfakekey/abi-sizeof-FakeKey "fkp/A-sizeof-FakeKey " "48" fk_line libfakekey/abi-off-xdpy "fkp/A-off-xdpy " "0" fk_line libfakekey/abi-off-min-keycode "fkp/A-off-min-keycode " "4" fk_line libfakekey/abi-off-max-keycode "fkp/A-off-max-keycode " "8" fk_line libfakekey/abi-off-n-keysyms "fkp/A-off-n-keysyms " "12" fk_line libfakekey/abi-off-keysyms "fkp/A-off-keysyms " "16" fk_line libfakekey/abi-off-held-keycode "fkp/A-off-held-keycode " "20" fk_line libfakekey/abi-off-held-state-flags "fkp/A-off-held-state-flags " "24" fk_line libfakekey/abi-off-modifier-table "fkp/A-off-modifier-table " "28" fk_line libfakekey/abi-off-shift-mod-index "fkp/A-off-shift-mod-index " "36" fk_line libfakekey/abi-off-alt-mod-index "fkp/A-off-alt-mod-index " "40" fk_line libfakekey/abi-off-meta-mod-index "fkp/A-off-meta-mod-index " "44" # modifier_table is KeyCode[8] and KeyCode is a byte, so this one is 8 on # BOTH arms -- and that is why it is worth having beside the offsets: it is # the member whose size does NOT move, so a build where it moved has a # KeyCode that is no longer a byte, which nothing else here would localise. fk_line libfakekey/abi-sizeof-modifier-table "fkp/A-sizeof-modifier-table " "8" # The public widths the layout above is built from. These are the narrower # assertion, and the one a consumer's own translation unit shares. fk_line libfakekey/abi-t-Display-ptr "fkp/A-t-Display-ptr " "4" fk_line libfakekey/abi-t-KeySym "fkp/A-t-KeySym " "4" fk_line libfakekey/abi-t-KeySym-ptr "fkp/A-t-KeySym-ptr " "4" fk_line libfakekey/abi-t-KeyCode "fkp/A-t-KeyCode " "1" fk_line libfakekey/abi-t-Bool "fkp/A-t-Bool " "4" fk_line libfakekey/abi-t-int "fkp/A-t-int " "4" fk_line libfakekey/abi-t-enum "fkp/A-t-enum " "4" # The premise section 7 stands on, asserted rather than assumed. fk_line libfakekey/abi-handle-block-covers "fkp/A-handle-block-covers " "yes" fk_line libfakekey/abi-handle-block-bytes "fkp/A-handle-block-bytes " "4096" # ------------------------------------------------------------------------- # 5. THE HEADER'S CONSTANTS, and the X indices the library's own table is # sized and addressed by. Arch-independent; measured on the reference build. # # FakeKeyModifier IS NOT AN X MODIFIER MASK, and the values are how you know. # FAKEKEYMOD_SHIFT is 2, which is X's LockMask -- ShiftMask is 1. The two sets # collide on CONTROL (4) and ALT/Mod1 (8) by coincidence and disagree on # SHIFT, so a reader who assumed they were the same set would be right two # times in three. They are never mixed in practice: fakekey_send_keyevent # branches on the flag and then indexes fk->modifier_table[ShiftMapIndex] # (libfakekey.c:247), never passing a flag anywhere a mask is expected. # Pinning both sets side by side is what keeps that separation visible. fk_line libfakekey/hdr-FAKEKEYMOD_SHIFT "fkp/H-FAKEKEYMOD_SHIFT " "2" fk_line libfakekey/hdr-FAKEKEYMOD_CONTROL "fkp/H-FAKEKEYMOD_CONTROL " "4" fk_line libfakekey/hdr-FAKEKEYMOD_ALT "fkp/H-FAKEKEYMOD_ALT " "8" fk_line libfakekey/hdr-FAKEKEYMOD_META "fkp/H-FAKEKEYMOD_META " "16" fk_line libfakekey/x-ShiftMapIndex "fkp/H-ShiftMapIndex " "0" fk_line libfakekey/x-LockMapIndex "fkp/H-LockMapIndex " "1" fk_line libfakekey/x-ControlMapIndex "fkp/H-ControlMapIndex " "2" fk_line libfakekey/x-Mod1MapIndex "fkp/H-Mod1MapIndex " "3" fk_line libfakekey/x-Mod5MapIndex "fkp/H-Mod5MapIndex " "7" fk_line libfakekey/x-N-modifier-indexes "fkp/H-N-modifier-indexes " "8" fk_line libfakekey/x-ShiftMask "fkp/H-ShiftMask " "1" fk_line libfakekey/x-LockMask "fkp/H-LockMask " "2" fk_line libfakekey/x-ControlMask "fkp/H-ControlMask " "4" fk_line libfakekey/x-Mod1Mask "fkp/H-Mod1Mask " "8" # The keysym encoding fakekey_press ORs in for anything above Latin-1 # (libfakekey.c:444). Asserted as arithmetic rather than driven, because # driving it needs a Display -- see the section 7 note on accepting inputs. fk_line libfakekey/x-unicode-keysym-base "fkp/H-unicode-keysym-base " "16777216" # ------------------------------------------------------------------------- # 6. THE DISPLAY THAT IS NOT THERE -- the documented no-server path, RUN. # # Not a prediction and not a substitute: XOpenDisplay returns NULL because # this image has no server, fakekey_init's own guard returns NULL because it # was handed one, and `NULL on fail' is what fakekey.h documents. This is the # library behaving as specified on the inputs this image actually produces. fk_line libfakekey/init-nodisplay-xopen "fkp/I-nodisplay-xopen " "NULL" fk_line libfakekey/init-nodisplay-null "fkp/I-nodisplay-init " "NULL" # DISPLAY pointing at a TCP port nothing listens on. The assertion the ticket # asks for is that this REFUSES rather than blocking on the connect, and the # contained case below is what carries it: the fixture is bounded at 20s, so a # connect that hung would report `no (exceeded 20s)' here instead of `yes'. fk_line libfakekey/init-deaddisplay-xopen "fkp/I-deaddisplay-xopen " "NULL" fk_line libfakekey/init-deaddisplay-null "fkp/I-deaddisplay-init " "NULL" # The same refusal asked directly, with no environment in the way -- the guard # on its own, independent of whatever XOpenDisplay decided. fk_line libfakekey/init-explicit-null "fkp/I-explicit-null-init " "NULL" fk_line libfakekey/init-nodisplay-bounded "fkp/I-nodisplay-contained " "yes" fk_line libfakekey/init-deaddisplay-bounded "fkp/I-deaddisplay-contained " "yes" # ------------------------------------------------------------------------- # 7. THE UTF-8 REJECT BOUNDARY -- libfakekey.c's own decoder, executed. # # Every case here drives utf8_to_ucs4 (libfakekey.c:69-137) out of # libfakekey.a on a zeroed handle and asserts fakekey_press's documented # failure return, 0, reached at libfakekey.c:429 before fk->xdpy is used. # Section 4's handle-block-covers case is what makes the zeroed handle sound. # # THERE IS DELIBERATELY NO ACCEPTING CASE. A valid character falls through to # fakekey_press_keysym and XKeysymToKeycode(fk->xdpy, ...), and fk->xdpy is # NULL on this handle. The reject side is the whole of what an image with no # server can execute here, and it is also the whole of what the ticket asks # for -- a zero-length buffer and a byte sequence that is not valid UTF-8. fk_line libfakekey/utf8-zero-length "fkp/E-zero-length " "0" # The four ways a byte sequence can fail to be UTF-8, one case each, because # they take four different branches of the decoder and a red should say which. fk_line libfakekey/utf8-lone-continuation "fkp/E-lone-cont " "0" fk_line libfakekey/utf8-truncated-2byte "fkp/E-trunc-2byte " "0" fk_line libfakekey/utf8-bad-continuation "fkp/E-bad-cont " "0" fk_line libfakekey/utf8-lead-fe "fkp/E-lead-fe " "0" fk_line libfakekey/utf8-lead-ff "fkp/E-lead-ff " "0" # len_bytes = -1 is fakekey.h's documented "ends with 0" sentinel; it is the # one input that reaches the strlen branch at libfakekey.c:417, and with an # empty string it lands back on the zero-length rejection. fk_line libfakekey/utf8-negative-length "fkp/E-neg-len-empty " "0" # The idle-handle early returns. Both are complete executions of real library # code: neither touches fk->xdpy when held_keycode is 0. fk_line libfakekey/idle-release-returned "fkp/E-release-idle-returned " "yes" fk_line libfakekey/idle-repeat-returned "fkp/E-repeat-idle-returned " "yes" # And the handle is STILL IDLE after both -- proved by a press that is # rejected on the decoder (0, from libfakekey.c:429) rather than on the # `key is already held down' guard at libfakekey.c:409, which returns 0 too. # The two returns are indistinguishable by value, which is exactly why this # case is worth stating: it is the release/repeat pair leaving held_keycode # alone that keeps the decoder reachable at all. fk_line libfakekey/idle-press-after "fkp/E-press-after-idle-calls " "0" fk_line libfakekey/utf8-bounded "fkp/E-contained " "yes" # ------------------------------------------------------------------------- # 8. A NULL HANDLE -- CONTAINMENT ONLY, AND THE REASON IS UPSTREAM'S. # # The ticket asks for a NULL handle passed to fakekey_press and # fakekey_release, "each asserted to produce the documented result rather than # a crash or an out-of-bounds read". THERE IS NO DOCUMENTED RESULT. # fakekey_press opens `if (fk->held_keycode)' (libfakekey.c:409) and # fakekey_release opens `if (!fk->held_keycode)' (libfakekey.c:441); both load # through fk, neither checks it, and fakekey.h promises nothing for a NULL # handle. On the x86-64 reference build all three fault with SIGSEGV. # # So asserting a return value here would be asserting a guarantee this library # does not make, and a green case would mean the platform silently tolerated a # null dereference rather than that the library handled it. What IS assertable # is containment: the call ends its own process, inside a bound, without # taking the run with it. That is the whole of what the platform promises, and # it is worth pinning because the alternative failure -- a wedged guest -- # costs every other suite in the image its results. # # The disposition is reported beside each case as evidence and is NOT asserted # to a value: whether a null load faults or reads zero is a property of the # runtime's linear memory, not of this port, and pinning it here would make # this suite red for a platform change it has no stake in. fk_line libfakekey/null-release-contained "fkp/N-release-contained " "yes" fk_line libfakekey/null-repeat-contained "fkp/N-repeat-contained " "yes" fk_line libfakekey/null-press-contained "fkp/N-press-contained " "yes" for c in release repeat press; do if grep -Fq "fkp/N-$c-contained-disp " "$work/out" 2>/dev/null; then bst_ok libfakekey/null-$c-disposition-reported else bst_notok libfakekey/null-$c-disposition-reported \ "the probe reported containment for $c but no disposition line" fi done # ------------------------------------------------------------------------- # 9. THE ENTRY-POINT CENSUS, out of libfakekey.a. # # Each name was taken by ADDRESS in the probe, so the probe's own LINK is what # proved the archive still contains it; these cases assert that the link that # produced THIS binary saw all seven. The floor is pinned in the bbappend, # which refuses the build if the probe's table shrinks. fk_line libfakekey/census-count "fkp/C-entry-points " "7" for f in fakekey_init fakekey_press fakekey_press_keysym fakekey_release \ fakekey_repeat fakekey_reload_keysyms fakekey_send_keyevent; do fk_line libfakekey/census-$f "fkp/C-have-$f " "yes" done fi rm -rf "$work"