. "$BST_LIB" require perl libconvert-asn1-perl/present # The suite is four layers, each honest about what it can see: # 1. filesystem facts -- what the port SHIPS, and both directions of the # RDEPENDS correction the bbappend exists for. Asserted before anything # starts perl, so they hold even on a boot where the interpreter cannot # load a module at all. # 2. can perl LOAD Convert::ASN1 on this boot, classified on the DIAGNOSTIC. # 3. the battery, driven by the payload -- 130-odd cases at BYTE level. # 4. the platform defect this port is shaped around, probed in fresh perls. # Layer 3 is everything the ticket asks for, and it is the layer a broken # interpreter takes out wholesale: the payload runs all its cases in ONE perl # process, so an abort at load costs every case at once. Layer 2 exists so that # reads as one attributed red rather than 130 bare mismatches. V=$(ls -d /usr/lib/perl5/vendor_perl/* 2>/dev/null | head -1) CORE=$(ls -d /usr/lib/perl5/5.* 2>/dev/null | head -1) # ------------------------- 1. what the port SHIPS: filesystem facts ---------- check libconvert-asn1-perl/vendor-dir test -n "$V" check libconvert-asn1-perl/module-installed test -f "$V/Convert/ASN1.pm" check libconvert-asn1-perl/io-installed test -f "$V/Convert/ASN1/IO.pm" check libconvert-asn1-perl/parser-installed test -f "$V/Convert/ASN1/parser.pm" check libconvert-asn1-perl/encode-installed test -f "$V/Convert/ASN1/_encode.pm" check libconvert-asn1-perl/decode-installed test -f "$V/Convert/ASN1/_decode.pm" check libconvert-asn1-perl/payload-installed \ test -f "$BST_DATA/libconvert-asn1-perl-selftest.pl" # BOTH DIRECTIONS OF THE RDEPENDS CORRECTION, which is half this port's # substance and is otherwise invisible on a booted image. poky names a # TEST-only dependency in the runtime package and a genuine RUNTIME one under # -ptest; the bbappend swaps them. Math::BigInt is needed for every integer past # +/-2^31 (layer 3's RSA-modulus cases fail without it); Test::More costs 59 # packages and reddens a neighbouring suite. Asserted as ordinary reds: both are # a documented part of this port's closure now, so a change in either direction # is a regression to report. check libconvert-asn1-perl/dep-math-bigint test -f "$CORE/Math/BigInt.pm" check libconvert-asn1-perl/no-test-more test ! -f "$CORE/Test/More.pm" # Two helpers the load guard (layer 2) and the platform probes (layer 4) share, # because both have to read a perl diagnostic on an image where #154 can abort # any interpreter at any time, and disagreeing about what counts as #154 is how # an attributed red turns back into a bare one. # # The interpreter's locale warning is a four-line preamble on this image and is # NOT the failure: it precedes the real diagnostic and would otherwise fill the # 100-char detail field, leaving the red reading "Setting locale failed" -- the # wrong diagnosis in the one field a later reader attributes by. That masking # cost BRINTOS-1005's investigation its first hour. asn1_diag() { printf '%s\n' "$1" | awk '/^perl: warning/ { skip=1; next } /^[ \t]/ && skip { next } { skip=0; print }' } # The pattern set is WIDE on purpose and was widened by measurement in # BRINTOS-1011, not by guesswork: glibc has a dozen spellings for one abort, and # missing one turns an attributed red into a false alarm. This port met # "corrupted size vs. prev_size", NOT the "mremap_chunk" the investigation was # named after -- which is the case in point. asn1_is_154() { case "$1" in *mremap_chunk*|*munmap_chunk*|*"corrupted size"*|*"corrupted double-linked list"*|\ *"double free or corruption"*|*"free(): "*|*"malloc(): "*|*"realloc(): "*) return 0 ;; esac return 1 } ASN1_154="linux-in-the-browser#154 -- perl aborts in glibc's allocator while compiling a module" # --- 4. the platform defect this port is shaped around ---------------------- # Run as a function so that BOTH paths reach it: the normal one at the end of # the file, and layer 2's guard when the battery cannot run at all. Each probe # starts a FRESH perl, which is what makes it independent of whatever state the # payload's interpreter reached. asn1_platform_probes() { # --- the platform defect this port is shaped around ------------------------ # linux-in-the-browser#93: deleting a declared sub from a stash walks a freed # referrer in the backref list and panics. Socket.pm does exactly that (lines # 890-892, "reduces the size of %Socket:: by about 12K") once its XS boot has # taken, so `use Socket` dies and takes Convert::ASN1::IO with it. # # Each probe runs in a FRESH perl, and that is load-bearing: in the payload's # own interpreter the tolerant require has already half-loaded Socket, and the # delete does not panic a second time -- so an in-process probe reports LOADS # and measures nothing. These go red the day #93 closes, which is the # notification that the bbappend patch can come out. so=$(perl -e 'use Socket; print "LOADS\n"' 2>&1) case "$so" in *panic:*) bst_ok libconvert-asn1-perl/socket-panics ;; *LOADS*) bst_notok libconvert-asn1-perl/socket-panics \ "Socket loads now — linux-in-the-browser#93 may be fixed; drop the bbappend patch" ;; *) # On a #154 boot the allocator abort gets there before the panic does, so # this probe measures the interpreter rather than #93. Attributed, not bare. sod=$(asn1_diag "$so") if asn1_is_154 "$sod"; then bst_notok libconvert-asn1-perl/socket-panics \ "$(_bst_1line "$sod") -- $ASN1_154 (whether #93 still panics is unmeasurable on this boot)" else bst_notok libconvert-asn1-perl/socket-panics "$(_bst_1line "$sod")" fi ;; esac # the same fault at its narrowest, so the suite carries the reproducer and not # only its consequence: one declared sub, deleted from its own stash. sd=$(perl -e 'package F; sub bar { 1 } delete $F::{bar}; print "NOPANIC\n"' 2>&1) case "$sd" in *panic:*) bst_ok libconvert-asn1-perl/stash-delete-panics ;; *NOPANIC*) bst_notok libconvert-asn1-perl/stash-delete-panics \ "the stash delete no longer panics — linux-in-the-browser#93 may be fixed" ;; *) sdd=$(asn1_diag "$sd") if asn1_is_154 "$sdd"; then bst_notok libconvert-asn1-perl/stash-delete-panics \ "$(_bst_1line "$sdd") -- $ASN1_154 (the #93 reproducer could not run on this boot)" else bst_notok libconvert-asn1-perl/stash-delete-panics "$(_bst_1line "$sdd")" fi ;; esac # the property the whole workaround rests on: the panic is trappable and leaves # a working interpreter that still exits 0. Without this an eval around the # require would not be enough and the port would need a perl rebuild instead. tr=$(perl -e 'my $ok = eval { require Socket; 1 }; print "TRAPPED=", ($ok ? "no" : "yes"), " ALIVE=", 1+1, "\n"' 2>&1); trrc=$? trv=$(printf '%s' "$tr" | sed -n 's/.*\(TRAPPED=[a-z]* ALIVE=[0-9]*\).*/\1/p') trd=$(asn1_diag "$tr") # These two are the property the whole workaround rests on, so when they cannot # be measured that has to be said rather than left reading as a refuted claim: # under #154 the interpreter aborts before the eval can report anything, which # is the allocator's answer and not evidence that the panic is untrappable. if [ "$trv" = "TRAPPED=yes ALIVE=2" ]; then bst_ok libconvert-asn1-perl/panic-trappable elif asn1_is_154 "$trd"; then bst_notok libconvert-asn1-perl/panic-trappable \ "rc=$trrc $(_bst_1line "$trd") -- $ASN1_154 (trappability unmeasurable on this boot)" else bst_notok libconvert-asn1-perl/panic-trappable "want:'TRAPPED=yes ALIVE=2' got:'$trv'" fi if [ "$trrc" = 0 ]; then bst_ok libconvert-asn1-perl/panic-exit-clean elif asn1_is_154 "$trd"; then bst_notok libconvert-asn1-perl/panic-exit-clean \ "rc=$trrc -- $ASN1_154 (the abort is the allocator's, not the trapped panic's)" else bst_notok libconvert-asn1-perl/panic-exit-clean "want:'0' got:'$trrc'" fi } # ------------------ 2. can perl LOAD Convert::ASN1 on this boot at all? ------ # BRINTOS-WORKAROUND: linux-in-the-browser#154 remove -- perl aborts in glibc's # allocator while compiling a module, so the battery below cannot run on an # image that meets it; delete this guard and the battery runs unconditionally # again once #154 closes. # # The guard classifies on the DIAGNOSTIC and says which block it met, because # there are three ways this load can fail here and attributing a red to the # wrong one is the error a later reader cannot detect: #154's allocator abort # (the platform, not us), #93's backref panic ESCAPING the bbappend's tolerant # require (ours -- the patch did not take), and the module simply not being on # the image (ours). Only the first is a platform gap this port ships around. iout=$(perl -MConvert::ASN1 -e 'print "ASN1-LOAD-OK\n"' 2>&1); irc=$? case "$iout" in *ASN1-LOAD-OK*) bst_ok libconvert-asn1-perl/import-load ;; *) # The interpreter's locale warning is a four-line preamble on this image and # is NOT the failure: it precedes the real diagnostic and would otherwise # fill the 100-char detail field, leaving the red reading "Setting locale # failed" -- the wrong diagnosis in the one field a later reader attributes # by. This cost BRINTOS-1005's investigation its first hour. idiag=$(asn1_diag "$iout") [ -n "$idiag" ] || idiag=$iout if asn1_is_154 "$idiag"; then iwhy=$ASN1_154 else case "$idiag" in *"Can't locate Convert/ASN1.pm"*) iwhy="OURS -- Convert::ASN1 is not on this image or is outside @INC; the port did not install" ;; *panic:*) iwhy="OURS -- linux-in-the-browser#93's panic ESCAPED the bbappend's tolerant require; the patch did not take" ;; *"Can't locate"*) iwhy="OURS -- a module in Convert::ASN1's closure is missing from this image; read the name in the diagnostic" ;; *) if [ "$irc" = 134 ]; then iwhy="unclassified SIGABRT -- rc=134 with no allocator diagnostic; probably #154 with a spelling this guard has not seen, but not asserted as one" else iwhy="unclassified -- none of #154's allocator abort, #93's panic, or a missing-module diagnostic" fi ;; esac fi bst_notok libconvert-asn1-perl/import-load "rc=$irc $(_bst_1line "$idiag") -- $iwhy" # Named rather than silent. The ticket's headline criterion is the WIRE # FORMAT -- a schema compiled, a structure encoded to DER with the bytes # asserted, decoded back and compared, and a truncated encoding rejected -- # and that is exactly what could not be measured. A suite that merely # stopped here would report its filesystem greens and read as a pass. bst_notok libconvert-asn1-perl/codec-unverified \ "not run: perl cannot load Convert::ASN1 ($iwhy) -- the DER encode/decode round trip, the hand-derived X.690 byte assertions, the OPTIONAL-field handling and the truncated-encoding refusal are unverified on wasm32-hwjs" # layer 4 still runs: it probes the platform in FRESH interpreters and does # not need Convert::ASN1 loadable, so it keeps reporting whether #93 is # still live on a boot where the battery cannot. asn1_platform_probes exit 0 ;; esac # Convert::ASN1 is pure Perl, so the whole port is @INC content: the module has # to be found, loaded, and produce the right BYTES. The payload does the # measuring and prints one tagged line per value; this file names and compares # them, so a single wrong answer is one red case rather than one red suite. # # What is different about this port is that its output is a wire format. Every # encoding asserted below was derived from X.690 by hand -- tag, length, # content -- not read back out of the module, because a codec compared only # against itself agrees with its own bugs. The decode side is then checked # against the same literals, so encoder and decoder cannot cover for each other. out=$(perl "$BST_DATA/libconvert-asn1-perl-selftest.pl" 2>&1); rc=$? case "$out" in *ALL-ASN1-OK*) all=1 ;; *) all=0 ;; esac if [ "$rc" -eq 0 ] && [ "$all" -eq 1 ]; then bst_ok libconvert-asn1-perl/all-ok else bst_notok libconvert-asn1-perl/all-ok "rc=$rc $(_bst_1line "$out")"; fi val() { printf '%s\n' "$out" | awk -v t="$1" '$1==t{ $1=""; sub(/^ /,""); print; exit }'; } # --- the module, and the load-time dependencies it drags in ----------------- check_eq libconvert-asn1-perl/version 0.34 "$(val R1-version)" case "$(val R2-inc-path)" in /usr/*) bst_ok libconvert-asn1-perl/installed-path ;; *) bst_notok libconvert-asn1-perl/installed-path "ASN1.pm resolved to $(val R2-inc-path)" ;; esac # Stock upstream, this module is UNLOADABLE here and the reason is nowhere near # ASN.1: ASN1.pm's own BEGIN requires ::IO unconditionally (the pure-Perl branch # always runs, there being no XS &_encode), IO.pm does `use Socket` at file # scope, and loading Socket panics this arm's perl (see the block at the end of # this file). The port's bbappend makes that one require tolerant, so what ships # is a codec-only Convert::ASN1 -- these four cases are that shape, stated as # facts rather than left implicit, and every one of them changes the day # linux-in-the-browser#93 closes and the patch comes out. check_eq libconvert-asn1-perl/io-not-loaded NO "$(val R3-io-loaded)" check_eq libconvert-asn1-perl/io-unavailable SET "$(val R7-io-unavailable)" # %INC is NOT a witness for "did Socket load": perl records the file before # running its body and the panic unwinds past the cleanup, so the entry survives # a load that never completed. Pinned because the obvious assertion here (%INC # has no Socket) reads true and is wrong -- io-unavailable is what to trust. check_eq libconvert-asn1-perl/socket-inc-stale YES "$(val R4-socket-loaded)" # the recorded reason is the panic itself, not a missing file -- which is what # distinguishes "the platform cannot load Socket" from "perl-module-socket was # dropped from the image", two states that would otherwise look identical here. case "$(val R8-io-reason)" in panic:*) bst_ok libconvert-asn1-perl/io-reason-is-panic ;; *) bst_notok libconvert-asn1-perl/io-reason-is-panic "reason was $(val R8-io-reason)" ;; esac check_eq libconvert-asn1-perl/encode-loaded YES "$(val R5-encode-loaded)" check_eq libconvert-asn1-perl/encode-works FALSE "$(val R9-encode-is-utf8)" check_eq libconvert-asn1-perl/parser-loaded YES "$(val R6-parser-loaded)" # --- the ticket's schema: integer, string, sequence, optional -------------- check_eq libconvert-asn1-perl/prepare YES "$(val R10-prepare)" check_eq libconvert-asn1-perl/prepare-err none "$(val R11-prepare-err)" check_eq libconvert-asn1-perl/find YES "$(val R12-find)" check_eq libconvert-asn1-perl/encode YES "$(val R13-enc-ok)" check_eq libconvert-asn1-perl/encode-err none "$(val R14-enc-err)" # 30 1C | 02 02 03E8 (INTEGER 1000) | 13 07 "brintOS" (PrintableString) # | 01 01 FF (BOOLEAN TRUE, DER's 0xFF not 0x01) # | 30 0A 020101 020180 0202012C (SEQUENCE OF INTEGER 1, -128, 300) # The OPTIONAL OCTET STRING is absent, so no 04 TLV appears at all -- an encoder # that emitted an empty one instead would still decode, and would be wrong. check_eq libconvert-asn1-perl/der \ 301C020203E813076272696E744F530101FF300A0201010201800202012C "$(val R15-der)" check_eq libconvert-asn1-perl/der-len 30 "$(val R16-der-len)" # The same value with the OPTIONAL field present: one 04 02 0102 TLV inserted in # schema order, the outer length grown by exactly 4, nothing else moved. check_eq libconvert-asn1-perl/der-opt \ 3020020203E813076272696E744F530101FF04020102300A0201010201800202012C "$(val R17-der-opt)" check_eq libconvert-asn1-perl/der-opt-len 34 "$(val R18-der-opt-len)" # --- decode back, and compare the structure -------------------------------- check_eq libconvert-asn1-perl/decode YES "$(val R20-dec-ok)" check_eq libconvert-asn1-perl/decode-err none "$(val R21-dec-err)" check_eq libconvert-asn1-perl/dec-id 1000 "$(val R22-id)" check_eq libconvert-asn1-perl/dec-label brintOS "$(val R23-label)" check_eq libconvert-asn1-perl/dec-bool TRUE "$(val R24-active)" check_eq libconvert-asn1-perl/dec-coords 1,-128,300 "$(val R26-coords)" check_eq libconvert-asn1-perl/dec-keys active,coords,id,label "$(val R27-keys)" # An absent OPTIONAL must not materialise as an undef key: `exists` is how a # caller tells "not sent" from "sent empty", and a decoder that autovivifies it # destroys that distinction while every value case above still passes. check_eq libconvert-asn1-perl/opt-absent ABSENT "$(val R25-tag)" check_eq libconvert-asn1-perl/opt-present 0102 "$(val R29-opt-tag)" check_eq libconvert-asn1-perl/opt-keys active,coords,id,label,tag "$(val R30-opt-keys)" # An INTEGER that comes back as a perl STRING still prints 1000 and compares # equal; it is only visible numerically, and it is how a codec silently changes # a document's types. check_eq libconvert-asn1-perl/int-is-number NUMBER "$(val R28-id-num)" check_eq libconvert-asn1-perl/roundtrip SAME "$(val R31-roundtrip)" check_eq libconvert-asn1-perl/roundtrip3 SAME "$(val R32-roundtrip3)" # --- truncated and malformed encodings are REJECTED ------------------------ # The ticket's third requirement. A decoder that returns a partial structure is # worse than one that fails, because the caller cannot tell -- so each case # asserts that NO value came back, never that some particular error was raised. check_eq libconvert-asn1-perl/trunc-1 REJECTED "$(val R40-trunc-1)" check_eq libconvert-asn1-perl/trunc-half REJECTED "$(val R40-trunc-half)" check_eq libconvert-asn1-perl/trunc-hdr REJECTED "$(val R40-trunc-hdr)" check_eq libconvert-asn1-perl/empty REJECTED "$(val R40-empty)" check_eq libconvert-asn1-perl/garbage REJECTED "$(val R40-garbage)" check_eq libconvert-asn1-perl/wrong-tag REJECTED "$(val R40-wrong-tag)" check_eq libconvert-asn1-perl/short-len REJECTED "$(val R40-short-len)" check_eq libconvert-asn1-perl/long-len REJECTED "$(val R40-long-len)" check_eq libconvert-asn1-perl/trailing REJECTED "$(val R40-trailing)" # The complement: the nine above measure rejection only if the good encoding at # the same shape is still accepted. check_eq libconvert-asn1-perl/wellformed ACCEPTED "$(val R41-wellformed)" check_eq libconvert-asn1-perl/error-set SET "$(val R42-error-set)" # --- INTEGER edges: two's complement, minimal length, the sign byte -------- # The three rules an integer encoder gets wrong: 0 is one 00 octet and not zero # octets; a positive value whose top bit is set takes a leading 00 so it does # not read as negative (128 -> 00 80); a negative value is two's complement at # the shortest width that keeps the sign (-128 -> 80, -129 -> FF 7F). check_eq libconvert-asn1-perl/int-0 020100 "$(val R50-int-0)" check_eq libconvert-asn1-perl/int-1 020101 "$(val R50-int-1)" check_eq libconvert-asn1-perl/int-127 02017F "$(val R50-int-127)" check_eq libconvert-asn1-perl/int-128 02020080 "$(val R50-int-128)" check_eq libconvert-asn1-perl/int-255 020200FF "$(val R50-int-255)" check_eq libconvert-asn1-perl/int-256 02020100 "$(val R50-int-256)" check_eq libconvert-asn1-perl/int-m1 0201FF "$(val R50-int-m1)" check_eq libconvert-asn1-perl/int-m128 020180 "$(val R50-int-m128)" check_eq libconvert-asn1-perl/int-m129 0202FF7F "$(val R50-int-m129)" check_eq libconvert-asn1-perl/int-65535 020300FFFF "$(val R50-int-65535)" check_eq libconvert-asn1-perl/int-m32768 02028000 "$(val R50-int-m32768)" check_eq libconvert-asn1-perl/int-max32 02047FFFFFFF "$(val R50-int-2147483647)" check_eq libconvert-asn1-perl/int-min32 020480000000 "$(val R50-int-m2147483648)" check_eq libconvert-asn1-perl/int-rt-0 0 "$(val R51-rt-0)" check_eq libconvert-asn1-perl/int-rt-128 128 "$(val R51-rt-128)" check_eq libconvert-asn1-perl/int-rt-m1 -1 "$(val R51-rt-m1)" check_eq libconvert-asn1-perl/int-rt-m128 -128 "$(val R51-rt-m128)" check_eq libconvert-asn1-perl/int-rt-m129 -129 "$(val R51-rt-m129)" check_eq libconvert-asn1-perl/int-rt-max32 2147483647 "$(val R51-rt-2147483647)" check_eq libconvert-asn1-perl/int-rt-min32 -2147483648 "$(val R51-rt-m2147483648)" # --- every other universal type the ticket's users need, in one structure -- # 30 36 | 0101 00 (FALSE) | 0500 (NULL) | 0609 2A864886F70D01010B (the OID for # sha256WithRSAEncryption, which is what makes the arc encoding worth pinning: # 1.2 packs into one 2A octet, then 840 and 113549 each into base-128 groups) # | 0A01 02 (ENUMERATED) | 0302 00A0 (BIT STRING, 0 unused bits) | 0402 00FF # | 0C05 "caf" C3A9 (UTF8String -- 4 characters, 5 bytes) | 1605 "a@b.c" # | 1305 "OK 42" | 1E04 00410042 (BMPString, UCS-2BE). check_eq libconvert-asn1-perl/types-enc YES "$(val R60-types-enc)" check_eq libconvert-asn1-perl/types-der \ 3036010100050006092A864886F70D01010B0A0102030200A0040200FF0C05636166C3A916056140622E6313054F4B2034321E0400410042 \ "$(val R61-types-der)" check_eq libconvert-asn1-perl/bool-false FALSE "$(val R62-bool-false)" check_eq libconvert-asn1-perl/null DEFINED-1 "$(val R63-null)" check_eq libconvert-asn1-perl/oid 1.2.840.113549.1.1.11 "$(val R64-oid)" check_eq libconvert-asn1-perl/enum 2 "$(val R65-enum)" check_eq libconvert-asn1-perl/bitstring A0 "$(val R66-bitstring)" check_eq libconvert-asn1-perl/bitstring-len 8 "$(val R67-bitlen)" check_eq libconvert-asn1-perl/octets 00FF "$(val R68-octets)" # The one string that is not bytes-in-bytes-out: UTF8String decodes to # CHARACTERS, so e-acute is one element at codepoint 233 and the string is 4 # long, not 5. Reported as codepoints because the tty cannot carry it as itself. check_eq libconvert-asn1-perl/utf8-cp 99,97,102,233 "$(val R69-utf8-cp)" check_eq libconvert-asn1-perl/utf8-len 4 "$(val R70-utf8-len)" check_eq libconvert-asn1-perl/ia5 a@b.c "$(val R71-ia5)" check_eq libconvert-asn1-perl/print 'OK 42' "$(val R72-print)" check_eq libconvert-asn1-perl/bmp 00410042 "$(val R73-bmp)" # --- tagging: implicit REPLACES the tag, explicit WRAPS it ----------------- # 3008 | 8001 05 -- [0] IMPLICIT: context primitive tag 0, the INTEGER's own # 02 is gone # | A103 020105 -- [1] EXPLICIT: context CONSTRUCTED tag 1 wrapping the # whole 02 01 05. Getting these two the same way round is the # single most common ASN.1 codec bug, and both decode to 5, so # only the bytes tell them apart. check_eq libconvert-asn1-perl/tagged-der 3008800105A103020105 "$(val R74-tagged-der)" check_eq libconvert-asn1-perl/tagged-imp 5 "$(val R75-tagged-imp)" check_eq libconvert-asn1-perl/tagged-exp 5 "$(val R76-tagged-exp)" # --- CHOICE, SET OF, nested SEQUENCE OF SEQUENCE --------------------------- # A CHOICE emits only the arm taken, with no wrapper of its own. check_eq libconvert-asn1-perl/choice-int 020107 "$(val R77-choice-i)" check_eq libconvert-asn1-perl/choice-str 130178 "$(val R78-choice-s)" check_eq libconvert-asn1-perl/choice-dec s=x "$(val R79-choice-dec)" check_eq libconvert-asn1-perl/setof 3109020103020101020102 "$(val R80-setof)" check_eq libconvert-asn1-perl/setof-dec 3,1,2 "$(val R81-setof-dec)" check_eq libconvert-asn1-perl/rows-der 301030060201011301613006020102130162 "$(val R86-rows-der)" check_eq libconvert-asn1-perl/rows-dec '1=a;2=b' "$(val R87-rows-dec)" # --- ANY: the property every X.509 and LDAP schema leans on ---------------- # ANY carries an already-encoded TLV through untouched. 300D | 0609 | 0500 # is literally an X.509 AlgorithmIdentifier for sha256WithRSAEncryption -- if # ANY re-wrapped or re-encoded its payload, this would not be that structure. check_eq libconvert-asn1-perl/any-der 300D06092A864886F70D01010B0500 "$(val R82-any-der)" check_eq libconvert-asn1-perl/any-oid 1.2.840.113549.1.1.11 "$(val R83-any-oid)" check_eq libconvert-asn1-perl/any-param 0500 "$(val R84-any-param)" check_eq libconvert-asn1-perl/any-absent ABSENT "$(val R85-any-absent)" # --- long-form length: 200 bytes of content cannot use the short form ------ # 04 81 C8: 0x81 says "one length octet follows", then 0xC8 = 200. A codec that # only ever emits the short form is correct for everything under 128 bytes and # wrong for every certificate. check_eq libconvert-asn1-perl/longlen-hdr 0481C8 "$(val R88-longlen-hdr)" check_eq libconvert-asn1-perl/longlen-len 203 "$(val R89-longlen-len)" check_eq libconvert-asn1-perl/longlen-rt SAME "$(val R90-longlen-rt)" # --- times: the POSIX (encode) and Time::Local (decode) paths -------------- # 180F "20010909014640Z" and 170D "010909014640Z" -- GeneralizedTime carries the # century, UTCTime does not. The offset is pinned with timezone => 0 so these # bytes do not depend on the guest's clock setting; the unconfigured round trip # below is the check that the epoch survives whatever offset the guest applies. check_eq libconvert-asn1-perl/time-enc YES "$(val R91-time-enc)" check_eq libconvert-asn1-perl/time-der \ 3020180F32303031303930393031343634305A170D3031303930393031343634305A "$(val R92-time-der)" check_eq libconvert-asn1-perl/time-g 1000000000 "$(val R93-time-g)" check_eq libconvert-asn1-perl/time-u 1000000000 "$(val R94-time-u)" check_eq libconvert-asn1-perl/time-tz-roundtrip SAME "$(val R97-time-tz-rt)" check_eq libconvert-asn1-perl/timelocal-loaded YES "$(val R95-timelocal-loaded)" # Decoding a time does NOT reach POSIX -- only REAL does, below. The recipe's # RDEPENDS name perl-module-posix, and this pair is what says which type earns # it, so a future trim of that list has a measurement to argue with. check_eq libconvert-asn1-perl/posix-not-for-time NO "$(val R96-posix-loaded)" # --- REAL: base-2 binary encoding, and the only user of POSIX -------------- # X.690 8.5: 0900 is zero (no content octets at all, not an encoded 0.0). 80 is # binary / base 2 / scale 0 / 1-byte exponent / positive; F6 is exponent -10 and # A0 is mantissa 160, so 160 * 2**-10 = 0.15625 exactly. C0 flips the sign bit. check_eq libconvert-asn1-perl/real-zero 0900 "$(val R101-real-zero)" check_eq libconvert-asn1-perl/real-eighth 090380F6A0 "$(val R102-real-eighth)" check_eq libconvert-asn1-perl/real-one 090380F980 "$(val R103-real-one)" check_eq libconvert-asn1-perl/real-neg 0903C0F880 "$(val R104-real-neg)" check_eq libconvert-asn1-perl/real-rt 0.15625 "$(val R105-real-rt)" check_eq libconvert-asn1-perl/real-rt-neg -0.5 "$(val R106-real-rt-neg)" check_eq libconvert-asn1-perl/posix-loaded YES "$(val R107-posix-loaded)" # --- what `encoding => DER` does and does not do --------------------------- # configure() takes DER and rejects a nonsense encoding, but this release # canonicalises nothing: SET OF comes out in insertion order in both modes, # where DER (X.690 11.6) requires the members sorted by their encodings. Pinned # in both so a future release that starts sorting reports itself -- it matters # to anyone verifying an X.509 signature, where the bytes must be canonical. check_eq libconvert-asn1-perl/setof-ber 3109020103020101020102 "$(val R108-setof-ber)" check_eq libconvert-asn1-perl/setof-der 3109020103020101020102 "$(val R109-setof-der)" check_eq libconvert-asn1-perl/der-mode-accepted YES "$(val R110-der-accepted)" check_eq libconvert-asn1-perl/bogus-encoding REJECTED "$(val R111-bogus-encoding)" # --- a bad schema is rejected, and says why -------------------------------- # prepare() returning false is only half of it: a caller needs error() to be # populated, and an undefined type name must not sail through to become a # runtime surprise. check_eq libconvert-asn1-perl/bad-schema REJECTED "$(val R98-bad-schema)" check_eq libconvert-asn1-perl/bad-schema-err SET "$(val R99-bad-schema-err)" check_eq libconvert-asn1-perl/undef-type REJECTED "$(val R100-undef-type)" # --- integers beyond an IV: the X.509 case this module exists for ---------- # poky names Math::BigInt in RDEPENDS:${PN}-ptest and not in RDEPENDS:${PN}; # the bbappend adds it, because an RSA modulus is an INTEGER and without it # i2osp/os2ip return undef for everything below. check_eq libconvert-asn1-perl/bigint-available YES "$(val R130-bigint-avail)" # 2**31 needs a 00 sign byte (00 80 00 00 00); 2**32 does not (01 00 00 00 00); # -(2**31+1) is two's complement at five bytes (FF 7F FF FF FF). check_eq libconvert-asn1-perl/big-2p31 02050080000000 "$(val R131-big-2147483648)" check_eq libconvert-asn1-perl/big-2p32 02050100000000 "$(val R131-big-4294967296)" check_eq libconvert-asn1-perl/big-neg 0205FF7FFFFFFF "$(val R131-big-m2147483649)" check_eq libconvert-asn1-perl/big-rt-2p31 2147483648 "$(val R132-bigrt-2147483648)" check_eq libconvert-asn1-perl/big-rt-2p32 4294967296 "$(val R132-bigrt-4294967296)" check_eq libconvert-asn1-perl/big-rt-neg -2147483649 "$(val R132-bigrt-m2147483649)" # 2**2047+1 -- an RSA-2048-sized modulus. 02 82 01 01 is INTEGER, long-form # length 0x0101 = 257 content bytes: a 00 sign byte plus 256 of magnitude, the # first of which is 80. 617 decimal digits. This is the case that says the port # can carry a certificate rather than only a toy. check_eq libconvert-asn1-perl/rsa-hdr 028201010080 "$(val R133-rsa-hdr)" check_eq libconvert-asn1-perl/rsa-len 261 "$(val R134-rsa-len)" check_eq libconvert-asn1-perl/rsa-tail 0001 "$(val R135-rsa-tail)" check_eq libconvert-asn1-perl/rsa-rt SAME "$(val R136-rsa-rt)" check_eq libconvert-asn1-perl/rsa-digits 617 "$(val R137-rsa-digits)" # the same modulus in the structure it travels in: RSAPublicKey ::= SEQUENCE { # modulus INTEGER, publicExponent INTEGER }. 30 82 01 0A wraps 266 bytes and the # tail 02 03 01 00 01 is the exponent 65537 -- byte for byte what a real key # carries. Here the value is a Math::BigInt OBJECT, the natural calling shape. check_eq libconvert-asn1-perl/key-hdr 3082010A02820101 "$(val R138-key-hdr)" check_eq libconvert-asn1-perl/key-len 270 "$(val R139-key-len)" check_eq libconvert-asn1-perl/key-tail 0203010001 "$(val R140-key-tail)" check_eq libconvert-asn1-perl/key-n-rt SAME "$(val R141-key-n-rt)" check_eq libconvert-asn1-perl/key-e 65537 "$(val R142-key-e)" # ...and the trap next to it, pinned because it fails SILENTLY. The same object # at TOP level encodes as zero with no error: _encode asks # UNIVERSAL::isa($stash,'HASH'), a Math::BigInt is a blessed hash, so the object # is taken for a stash and the value read out of it is undef. A caller gets a # well-formed encoding of the wrong number, which is worse than a failure. Pass # the decimal string at top level (rsa-hdr above); an object is fine in a field. check_eq libconvert-asn1-perl/obj-at-top-is-zero 020100 "$(val R143-obj-at-top)" check_eq libconvert-asn1-perl/obj-at-top-silent NONE "$(val R144-obj-at-top-err)" asn1_platform_probes