Fix Huffman decoding on big-endian systems

On PPC systems, HTTP2 & HPACK testcases were failing because
AWS.HTTP2.HPACK.Huffman.Decode was raising Protocol_Errors over inconsistent
padding.

The encoded bytestrings were correct; things were diverging in
AWS.HTTP2.HPACK.Decode, where bytes were misinterpreted when read as
RFC_Byte, due to that record's representation clause being target-dependent.

For example, if we break in that function right as it processes the first
byte of an encoded string, and that first byte is decimal integer 130…

  256            Byte := Get_Byte;
  (gdb) next
  258            if Bit.B0 = 1 then
  (gdb) p/t byte
  $8 = 10000010

In RFC_Byte's "Bₙ at 0 range i .. j" component clauses, by default, i and j
are interpreted differently depending on which bit ordering the target uses.
Thus on a little-endian platform like x86_64-linux:

  (gdb) p/t bit
  $9 = (
      b7 => 0,
      b6 => 1,
      b5 => 0,
      b4 => 0,
      b3 => 0,
      b2 => 0,
      b1 => 0,
      b0 => 1,
      b23 => 10,
      b22 => 0,
      b21 => 0,
      b20 => 10,
      b30 => 100,
      b41 => 10,
      b40 => 1000
    )

Whereas on a big-endian platform such as ppc64-linux:

  (gdb) p/t bit
  $9 = (
      b7 => 1,
      b6 => 0,
      b5 => 0,
      b4 => 0,
      b3 => 0,
      b2 => 0,
      b1 => 1,
      b0 => 0,
      b23 => 10,
      b22 => 0,
      b21 => 0,
      b20 => 10,
      b30 => 10,
      b41 => 1000,
      b40 => 10
    )

Fix this by picking an explicit Bit_Order for RFC_Byte, so that in those
range clauses, i and j are interpreted consistently across all platforms
(i.e. pick Low_Order_First so that "0" refers to the MSb, "7" to the LSb).

Also fix AWS.HTTP2.HPACK.Huffman.Decode, which presents a similar problem: a
Stream_Element is aliased as an array of bits, but the indexing order of that
array will depend on endianness.  Use a similar solution to

  2023-03-21 "Fix creation of Huffman decoding tree for big-endian
  platforms" (7eca5a10c)

That is, remove the aliasing array type, and rely on platform-independent
shifts.

TN: eng/toolchain/aws#4
This commit is contained in:
Kévin Le Gouguec
2023-09-26 14:47:19 +02:00
parent b22a3f4b7c
commit e97f27078a
7 changed files with 8 additions and 13 deletions

View File

@@ -1,2 +0,0 @@
ppc-linux XFAIL Server crash; see eng/toolchain/aws#4.
ppc64-linux XFAIL Server crash; see eng/toolchain/aws#4.

View File

@@ -1,2 +0,0 @@
ppc-linux XFAIL Server crash; see eng/toolchain/aws#4.
ppc64-linux XFAIL Server crash; see eng/toolchain/aws#4.

View File

@@ -1,2 +0,0 @@
ppc-linux XFAIL Server crash; see eng/toolchain/aws#4.
ppc64-linux XFAIL Server crash; see eng/toolchain/aws#4.

View File

@@ -1,2 +0,0 @@
ppc-linux XFAIL Server crash; see eng/toolchain/aws#4.
ppc64-linux XFAIL Server crash; see eng/toolchain/aws#4.

View File

@@ -1,2 +0,0 @@
ppc-linux XFAIL Server crash; see eng/toolchain/aws#4.
ppc64-linux XFAIL Server crash; see eng/toolchain/aws#4.

View File

@@ -380,7 +380,6 @@ package body AWS.HTTP2.HPACK.Huffman is
EOS : constant Unsigned_32 := 16#fffffffa#;
type Byte_Bits is array (0 .. 7) of Bit with Pack;
Iter : Node_Access := Root;
Padding : Natural := 0;
Pad_0 : Boolean := False;
@@ -390,7 +389,6 @@ package body AWS.HTTP2.HPACK.Huffman is
for K in Str'Range loop
declare
E : constant Stream_Element := Str (K);
Bits : Byte_Bits with Size => 8, Address => E'Address;
C : Character;
begin
-- Keep last four bytes to check for EOS
@@ -406,7 +404,8 @@ package body AWS.HTTP2.HPACK.Huffman is
for B in reverse 0 .. 7 loop
declare
Bit : constant Huffman.Bit := Bits (B);
Bit : constant Huffman.Bit :=
Huffman.Bit (Shift_Right (Unsigned_8 (E), B) and 1);
begin
if Decode_Bit (Iter, Bit, C) then
I := I + 1;

View File

@@ -28,6 +28,7 @@
------------------------------------------------------------------------------
with Interfaces;
with System;
with AWS.HTTP2.Connection;
with AWS.HTTP2.HPACK.Huffman;
@@ -93,6 +94,11 @@ package body AWS.HTTP2.HPACK is
B41 at 0 range 0 .. 3;
end record;
-- Pick an explicit bit indexing order for this record, otherwise
-- the position & ranges in the component clauses will be
-- interpreted differently depending on endianness.
for RFC_Byte'Bit_Order use System.Low_Order_First;
B_II : constant Bit2 := 2#01#;
-- Incremental Indexing