. "$BST_LIB" # libassuan is the GnuPG IPC library: the Assuan protocol gpg speaks to # gpg-agent, dirmngr, scdaemon and the pinentries. A session is a client and a # server trading newline-terminated lines over a descriptor pair -- commands # from the client, and from the server D (data), S (status), INQUIRE, OK and # ERR lines back. # # The distro is static-only, so what the image gets is /usr/lib/libassuan.a, # /usr/include/assuan.h, libassuan.pc, the aclocal macro, and poky's # binconfig-disabled refusal stub in place of libassuan-config. There is NO # executable in this package on this arm -- nothing here is reachable from a # shell, and a payload-only suite could assert only that an archive and a header # exist, which would pass just as happily if every entry point in the archive # trapped on first call. # # --------------------------------------------------------------------------- # WHY THIS SUITE IS A PROBE AND NOT A PAYLOAD LIST # # BRINTOS-217 is the precedent: oniguruma COMPILED and PACKAGED perfectly on # this arm and then returned silently wrong offsets to every caller. libassuan # is worse-placed for that failure mode than most, because it is a PROTOCOL # library -- it does not crash when it goes wrong, it emits a subtly malformed # or mis-escaped line that the far side accepts without complaint. # # So data/libassuan-probe is cross-linked with wasmcc-glibc against THE VERY # ARCHIVE THAT SHIPS (/usr/lib/libassuan.a over /usr/lib/libgpg-error.a), staged # to $TMPDIR and run here. Its source is src/libassuan_probe.c, where each group # is documented. It drives BOTH protocol halves in ONE process and with no fork: # the server against a pre-buffered command script over a pipe pair, and the # client against canned server responses over a socketpair. That matters for the # runner's budget as much as for coverage -- upstream's own tests fork+exec a # helper, and a spawn on wasm32 is a fresh module instantiation costing seconds # apiece (BRINTOS-333 spent seven minutes on ~150 of them). # # EVERY EXPECTED VALUE BELOW IS THE VALUE A NATIVE x86_64 BUILD OF THE IDENTICAL # 2.5.6 RELEASE PRODUCES, captured before this suite was ever run on target. # Nothing the probe prints is a pointer, a pid, a size_t width or a timestamp, # so no value here is ALLOWED to differ between the two machines: a single # disagreement is a defect, not a platform difference to reason about. # # ONE VALUE IS EXEMPT, AND IT IS COMPARED RATHER THAN PINNED: the version # STRING. libassuan builds it in configure, so it reads "2.5.6" from the # tarball's shipped configure and "2.5.6-unknown" from a build that autoreconfs # first, as poky does -- the same release either way. Pinning it would assert # how the package was built. The suite instead requires the shipped header, the # pkg-config file and the running archive to agree on whatever it is. # # --------------------------------------------------------------------------- # ONE UPSTREAM DEFECT THIS PORT FIXES, AND THE CASES THAT HOLD THE FIX IN PLACE # # assuan_get_flag() ends with `return TRACE_SUC1 (...)`, and that macro expands # to `_assuan_debug (...), 0` -- a comma expression valued 0 -- so the public # getter discards the flag it just computed and answers 0 for every flag. It # reproduces on a native x86_64 build of the unmodified release, so it is a # libassuan bug and not this arm's. The recipe carries the one-line fix # (0001-assuan_get_flag-return-the-flag-not-the-trace-macro-s.patch, # BRINTOS-UPSTREAM-FIX); run-ctx-flag-get, run-ctx-flag-clear, # run-ctx-begin-confidential and run-ctx-end-confidential are what hold it in # place -- all four report OK only against a patched library. incd=/usr/include lib=/usr/lib/libassuan.a pc=/usr/lib/pkgconfig/libassuan.pc hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "absent or empty: $2"; fi; } has() { case "$3" in *"$2"*) bst_ok "$1" ;; *) bst_notok "$1" "not found: $2" ;; esac; } # --- the payload ------------------------------------------------------------ # The archive and the header are the whole shipped surface, so their absence is # reported as its own case rather than as a probe that would not have linked. hasfile libassuan/lib-archive "$lib" hasfile libassuan/header-assuan-h "$incd/assuan.h" hasfile libassuan/header-assuan-32-h "$incd/assuan-32.h" hasfile libassuan/pkgconfig-file "$pc" hasfile libassuan/aclocal-macro /usr/share/aclocal/libassuan.m4 # assuan.h is a WORDSIZE DISPATCHER, not the header -- exactly as libgpg-error's # gpg-error.h is. It includes and forwards to assuan-32.h or # assuan-64.h, so every declaration below is read out of assuan-32.h. A suite # that read assuan.h would report a broken -dev for a correctly packaged one. dispatch=$(cat "$incd/assuan.h" 2>/dev/null) has libassuan/header-wordsize-dispatch '#include ' "$dispatch" hdr=$(cat "$incd/assuan-32.h" 2>/dev/null) pcbody=$(cat "$pc" 2>/dev/null) # THE VERSION IS ASSERTED AS AGREEMENT, NOT AS A LITERAL. libassuan derives its # version string in configure, and the string depends on how the package was # built rather than on which release it is: the tarball's own shipped configure # yields "2.5.6", while a build that autoreconfs first -- which poky does -- has # no git checkout to describe and yields "2.5.6-unknown". Both are the same # release. Pinning the literal would encode the build method and go red on a # correct package; what has to hold is that the header, the pkg-config file and # the library agree. The probe's run-version case checks the header against what # the library reports at RUN time; this checks the header against the .pc. hdrver=$(printf '%s\n' "$hdr" | sed -n 's/^#define ASSUAN_VERSION "\(.*\)"$/\1/p') pcver=$(printf '%s\n' "$pcbody" | sed -n 's/^Version: *//p') if [ -n "$hdrver" ]; then bst_ok libassuan/header-version else bst_notok libassuan/header-version "no ASSUAN_VERSION in $incd/assuan-32.h"; fi if [ -n "$hdrver" ] && [ "$hdrver" = "$pcver" ]; then bst_ok libassuan/header-pc-version-agree else bst_notok libassuan/header-pc-version-agree "header '$hdrver' vs libassuan.pc '$pcver'"; fi # The numeric macro is not configure-derived -- it is the release's own 0xMMNNPP # -- so it is asserted literally. has libassuan/header-version-number '#define ASSUAN_VERSION_NUMBER 0x020506' "$hdr" # The two typedefs every consumer names, and the response codes the client # parser returns -- a header that packaged without them is a broken -dev. has libassuan/header-context-type 'typedef struct assuan_context_s *assuan_context_t;' "$hdr" has libassuan/header-handler-type 'typedef gpg_error_t (*assuan_handler_t) (assuan_context_t, char *);' "$hdr" has libassuan/header-response-data '#define ASSUAN_RESPONSE_DATA 2' "$hdr" # THE ARCHIVE'S CONTENTS, WITHOUT BINUTILS. This image ships no `ar` and no # `nm`, and reaching for them is not merely unavailable but wrong here: host # binutils cannot read these members either -- every one is LLVM bitcode and # `nm` answers "file format not recognized", because -flto compile output on # this arm is IR rather than an ELF object. (That opacity is what broke # libgpg-error's own configure, which sized its public lock object by running # objdump over a compiled probe; see its 0001-gen-lock-obj patch.) # # So the names are asserted as BYTES in the archive: ar's member headers and the # archive symbol index both store plain ASCII, and grep is on the image. What # that cannot show -- that a name is DEFINED rather than merely referenced -- is # exactly what the probe below shows, by linking against this same archive and # calling through it. inar() { if grep -qa -- "$2" "$lib" 2>/dev/null; then bst_ok "$1"; else bst_notok "$1" "not in archive: $2"; fi; } # Members are libtool-named (libassuan_la-*.o), on this arm and natively alike; # libassuan_la-context.o is the one carrying the patched assuan_get_flag. inar libassuan/archive-context libassuan_la-context.o inar libassuan/archive-client libassuan_la-client.o inar libassuan/archive-handler libassuan_la-assuan-handler.o inar libassuan/archive-buffer libassuan_la-assuan-buffer.o inar libassuan/archive-pipe-srv libassuan_la-assuan-pipe-server.o inar libassuan/archive-socket libassuan_la-assuan-socket.o # The symbols a consumer links. inar libassuan/symbol-new assuan_new inar libassuan/symbol-transact assuan_transact inar libassuan/symbol-send-data assuan_send_data inar libassuan/symbol-pipe-srv assuan_init_pipe_server inar libassuan/symbol-get-flag assuan_get_flag # libassuan.pc names libgpg-error as its dependency; a port that lost that link # builds here and fails in the first consumer that trusts pkg-config. has libassuan/pkgconfig-name 'Name: libassuan' "$pcbody" has libassuan/pkgconfig-libs '-lassuan' "$pcbody" has libassuan/pkgconfig-requires 'gpg-error' "$pcbody" # poky's binconfig-disabled replaces libassuan-config with a stub that refuses # and exits non-zero. Asserting the refusal (rather than skipping it) is what # keeps a silently-restored, wrong-prefix config script from shipping. if [ -e /usr/bin/libassuan-config ]; then out=$(/usr/bin/libassuan-config --libs 2>&1); rc=$? if [ "$rc" -ne 0 ]; then bst_ok libassuan/binconfig-disabled else bst_notok libassuan/binconfig-disabled "libassuan-config answered (rc=0): $out"; fi else bst_skip libassuan/binconfig-disabled "no /usr/bin/libassuan-config on this image" fi # --- the library RUNNING, via the cross-linked probe ------------------------- probe=${TMPDIR:-/tmp}/bst-libassuan-probe.$$ if cp "$BST_DATA/libassuan-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then out=$("$probe" 2>&1) # identity, at run time and from the archive rather than from the header. # run-version is the probe's own header-vs-runtime check, made against the # header it was COMPILED with; run-version-value ties that runtime string to # the header that SHIPS, which nothing else here can do -- a -dev packaged # from a different build than its archive fails exactly this case and nothing # else. It is compared, not pinned, for the reason header-version is. has libassuan/run-version "LA-version OK" "$out" if [ -n "$hdrver" ]; then has libassuan/run-version-value "LA-version-value $hdrver" "$out" else bst_notok libassuan/run-version-value "no ASSUAN_VERSION in the shipped header to compare against" fi has libassuan/run-version-req-ok "LA-version-req-ok OK" "$out" has libassuan/run-version-req-older "LA-version-req-older OK" "$out" has libassuan/run-version-req-too-new "LA-version-req-too-new OK" "$out" has libassuan/run-version-number "LA-version-number 0x020506" "$out" # the context: every setter read back through its getter, because a context # field landing at the wrong offset is the arm-specific failure that would # make every protocol assertion below lie while still reporting OK has libassuan/run-ctx-new "LA-ctx-new OK" "$out" has libassuan/run-ctx-pointer "LA-ctx-pointer OK" "$out" has libassuan/run-ctx-err-source "LA-ctx-err-source OK" "$out" has libassuan/run-ctx-set-error-code "LA-ctx-set-error-code OK" "$out" has libassuan/run-ctx-set-error-src "LA-ctx-set-error-source OK" "$out" has libassuan/run-ctx-input-fd-unset "LA-ctx-input-fd-unset OK" "$out" has libassuan/run-ctx-output-fd-unset "LA-ctx-output-fd-unset OK" "$out" has libassuan/run-ctx-log-prefix "LA-ctx-log-prefix OK" "$out" has libassuan/run-ctx-release "LA-ctx-release OK" "$out" # THE FOUR THAT HOLD THE UPSTREAM FIX IN PLACE -- all four report OK only # against a library carrying 0001-assuan_get_flag-... (see the header above) has libassuan/run-ctx-flag-get "LA-ctx-flag-get OK" "$out" has libassuan/run-ctx-flag-clear "LA-ctx-flag-clear OK" "$out" has libassuan/run-ctx-begin-confid "LA-ctx-begin-confidential OK" "$out" has libassuan/run-ctx-end-confid "LA-ctx-end-confidential OK" "$out" # the allocator hooks are USED, not merely stored, and the library balances # its own frees through them has libassuan/run-mem-new-ext "LA-mem-new-ext OK" "$out" has libassuan/run-mem-hook-used "LA-mem-hook-used OK" "$out" has libassuan/run-mem-hooks-readback "LA-mem-hooks-readback OK" "$out" has libassuan/run-mem-balanced "LA-mem-balanced OK" "$out" # the server: registration, then the state machine itself has libassuan/run-srv-pipes "LA-srv-pipes OK" "$out" has libassuan/run-srv-script-write "LA-srv-script-write OK" "$out" has libassuan/run-srv-hello-line "LA-srv-hello-line OK" "$out" has libassuan/run-srv-register-echo "LA-srv-register-echo OK" "$out" has libassuan/run-srv-register-spec "LA-srv-register-specials OK" "$out" has libassuan/run-srv-register-long "LA-srv-register-long OK" "$out" has libassuan/run-srv-register-status "LA-srv-register-status OK" "$out" has libassuan/run-srv-register-okline "LA-srv-register-okline OK" "$out" has libassuan/run-srv-register-failit "LA-srv-register-failit OK" "$out" has libassuan/run-srv-register-option "LA-srv-register-option OK" "$out" has libassuan/run-srv-register-reset "LA-srv-register-reset OK" "$out" has libassuan/run-srv-register-bye "LA-srv-register-bye OK" "$out" has libassuan/run-srv-register-pre "LA-srv-register-pre OK" "$out" has libassuan/run-srv-register-post "LA-srv-register-post OK" "$out" has libassuan/run-srv-init "LA-srv-init OK" "$out" has libassuan/run-srv-accept "LA-srv-accept OK" "$out" has libassuan/run-srv-process "LA-srv-process OK" "$out" has libassuan/run-srv-transcript "LA-srv-transcript OK" "$out" has libassuan/run-srv-greeting "LA-srv-greeting OK" "$out" has libassuan/run-srv-echo-data "LA-srv-echo-data OK" "$out" has libassuan/run-srv-command-name "LA-srv-command-name OK" "$out" has libassuan/run-srv-status-line "LA-srv-status-line OK" "$out" has libassuan/run-srv-okay-line "LA-srv-okay-line OK" "$out" has libassuan/run-srv-err-registered "LA-srv-err-registered OK" "$out" has libassuan/run-srv-err-unknown "LA-srv-err-unknown OK" "$out" has libassuan/run-srv-option-seen "LA-srv-option-seen OK" "$out" has libassuan/run-srv-option-name "LA-srv-option-name OK" "$out" has libassuan/run-srv-option-value "LA-srv-option-value OK" "$out" has libassuan/run-srv-reset-seen "LA-srv-reset-seen OK" "$out" has libassuan/run-srv-bye-seen "LA-srv-bye-seen OK" "$out" # 10 pre-cmd against 11 post-cmd: post fires for the unknown command too, # pre only after the table lookup succeeds. 11/11 would mean NOSUCHCOMMAND # reached a handler. has libassuan/run-srv-pre-seen "LA-srv-pre-seen OK" "$out" has libassuan/run-srv-post-seen "LA-srv-post-seen OK" "$out" # the transcript's shape, so a target run is diffable rather than merely green has libassuan/run-srv-ok-count "LA-srv-ok-count 10" "$out" has libassuan/run-srv-err-count "LA-srv-err-count 2" "$out" # THE ESCAPING -- where a protocol library corrupts silently. '%', CR and LF # must render as %25/%0D/%0A and nothing else may be touched; a 2500-byte # payload must split across lines and reassemble to exactly 2500 bytes. has libassuan/run-data-specials "LA-data-specials OK" "$out" has libassuan/run-data-long-seen "LA-data-long-seen OK" "$out" has libassuan/run-data-long-bytes "LA-data-long-bytes OK" "$out" has libassuan/run-data-long-split "LA-data-long-split OK" "$out" has libassuan/run-data-dline-count "LA-data-dline-count 5" "$out" # the client half, against canned server responses over a socketpair has libassuan/run-cli-socketpair "LA-cli-socketpair OK" "$out" has libassuan/run-cli-script-write "LA-cli-script-write OK" "$out" has libassuan/run-cli-connect "LA-cli-connect OK" "$out" has libassuan/run-cli-transact-ok "LA-cli-transact-ok OK" "$out" has libassuan/run-cli-status-calls "LA-cli-status-calls OK" "$out" has libassuan/run-cli-status-line "LA-cli-status-line OK" "$out" # the de-escape is asserted to be the exact inverse of run-data-specials has libassuan/run-cli-data-len "LA-cli-data-len OK" "$out" has libassuan/run-cli-data-bytes "LA-cli-data-bytes OK" "$out" has libassuan/run-cli-err-code "LA-cli-err-code OK" "$out" has libassuan/run-cli-err-source "LA-cli-err-source OK" "$out" has libassuan/run-cli-release "LA-cli-release OK" "$out" # the client's line parser, driven directly over every response type has libassuan/run-parse-ok "LA-parse-ok OK" "$out" has libassuan/run-parse-err "LA-parse-err OK" "$out" has libassuan/run-parse-data "LA-parse-data OK" "$out" has libassuan/run-parse-status "LA-parse-status OK" "$out" has libassuan/run-parse-inquire "LA-parse-inquire OK" "$out" has libassuan/run-parse-end "LA-parse-end OK" "$out" has libassuan/run-parse-comment "LA-parse-comment OK" "$out" # the socket wrapper layer has libassuan/run-sock-init "LA-sock-init OK" "$out" has libassuan/run-sock-deinit "LA-sock-deinit OK" "$out" # The probe's own tally and its exit status. 77/77 is what the same source # scores natively against a host build of the identical patched release. has libassuan/run-summary "LA-SUMMARY 77/77" "$out" check_rc libassuan/run-exit0 0 "$probe" rm -f "$probe" else bst_notok libassuan/run-stage "cannot stage $BST_DATA/libassuan-probe" fi