From 34751d8bf921a2c07cf9a7ce9074756a3d936013 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 26 May 2023 14:10:38 +0200 Subject: libbb/dump: correct handling of 1-byte signed int format Signed-off-by: Denys Vlasenko --- libbb/dump.c | 37 +++++++++++++++++-------------------- testsuite/hexdump.tests | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/libbb/dump.c b/libbb/dump.c index dace481c2..49340b5a5 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -619,31 +619,31 @@ static NOINLINE void display(priv_dumper_t* dumper) } case F_INT: { union { - uint16_t val16; - uint32_t val32; - uint64_t val64; + int16_t ival16; + int32_t ival32; + int64_t ival64; } u; - int value = *bp; + int value = (signed char)*bp; switch (pr->bcnt) { case 1: break; case 2: - memcpy(&u.val16, bp, 2); - value = u.val16; + move_from_unaligned16(u.ival16, bp); + value = u.ival16; break; case 4: - memcpy(&u.val32, bp, 4); - value = u.val32; + move_from_unaligned32(u.ival32, bp); + value = u.ival32; break; case 8: - memcpy(&u.val64, bp, 8); + move_from_unaligned64(u.ival64, bp); //A hack. Users _must_ use %llX formats to not truncate high bits - printf(pr->fmt, (long long) u.val64); + printf(pr->fmt, (long long)u.ival64); goto skip; } printf(pr->fmt, value); - IF_OD(skip:) + skip: break; } case F_P: @@ -659,22 +659,19 @@ static NOINLINE void display(priv_dumper_t* dumper) conv_u(pr, bp); break; case F_UINT: { - unsigned ival; - unsigned short sval; - + unsigned value = (unsigned char)*bp; switch (pr->bcnt) { case 1: - printf(pr->fmt, (unsigned) *bp); break; case 2: - memcpy(&sval, bp, sizeof(sval)); - printf(pr->fmt, (unsigned) sval); + move_from_unaligned16(value, bp); break; case 4: - memcpy(&ival, bp, sizeof(ival)); - printf(pr->fmt, ival); + move_from_unaligned32(value, bp); break; + /* case 8: no users yet */ } + printf(pr->fmt, value); break; } } @@ -686,7 +683,7 @@ static NOINLINE void display(priv_dumper_t* dumper) } } } - endfu: + IF_OD(endfu:) if (dumper->endfu) { PR *pr; /* diff --git a/testsuite/hexdump.tests b/testsuite/hexdump.tests index 084156af4..be0379cfc 100755 --- a/testsuite/hexdump.tests +++ b/testsuite/hexdump.tests @@ -34,7 +34,7 @@ testing "hexdump thinks last full block can match" \ '' \ '\0\0\0\0\0\0\0\0\0\0\0\0' -testing "hexdump e %3_u" \ +testing "hexdump -e %3_u" \ "hexdump -e '16/1 \" %3_u\" \"\n\"'" \ "\ nul soh stx etx eot enq ack bel bs ht lf vt ff cr so si @@ -50,4 +50,36 @@ testing "hexdump e %3_u" \ "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"\ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"\ +testing "hexdump -e /1 %d" \ + "hexdump -e '16/1 \" %4d\" \"\n\"'" \ + "\ + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 + -128 -127 -126 -125 -124 -123 -122 -121 -120 -119 -118 -117 -116 -115 -114 -113 + -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 +" \ + "" \ +"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"\ +"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"\ +"\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"\ +"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"\ +"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"\ + +testing "hexdump -e /2 %d" \ + "hexdump -e '8/2 \" %6d\" \"\n\"'" \ + "\ + 256 770 1284 1798 2312 2826 3340 3854 + 4368 4882 5396 5910 6424 6938 7452 7966 + 29040 29554 30068 30582 31096 31610 32124 32638 + -32384 -31870 -31356 -30842 -30328 -29814 -29300 -28786 + -3600 -3086 -2572 -2058 -1544 -1030 -516 -2 +" \ + "" \ +"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"\ +"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"\ +"\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"\ +"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"\ +"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"\ + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb