@@ -27,49 +27,54 @@ const reportedDiagnosticEvent = {
2727const chunks = await toArray ( serializer ( [ diagnosticEvent ] ) ) ;
2828const defaultSerializer = new DefaultSerializer ( ) ;
2929defaultSerializer . writeHeader ( ) ;
30- const headerLength = defaultSerializer . releaseBuffer ( ) . length ;
31- const headerOnly = Buffer . from ( [ 0xff , 0x0f ] ) ;
32- const oversizedLengthHeader = Buffer . from ( [ 0xff , 0x0f , 0x7f , 0xff , 0xff , 0xff ] ) ;
33- const unsignedOversizedLengthHeader = Buffer . from ( [ 0xff , 0x0f , 0x80 , 0x00 , 0x00 , 0x00 ] ) ;
34- const truncatedLengthHeader = Buffer . from ( [ 0xff , 0x0f , 0x00 , 0x01 , 0x00 , 0x00 ] ) ;
30+ const headerOnly = Buffer . from ( defaultSerializer . releaseBuffer ( ) ) ;
31+ const headerLength = headerOnly . length ;
32+ const oversizedLengthHeader = Buffer . concat ( [ headerOnly , Buffer . from ( [ 0x7f , 0xff , 0xff , 0xff ] ) ] ) ;
33+ const unsignedOversizedLengthHeader = Buffer . concat ( [ headerOnly , Buffer . from ( [ 0x80 , 0x00 , 0x00 , 0x00 ] ) ] ) ;
34+ const truncatedLengthHeader = Buffer . concat ( [ headerOnly , Buffer . from ( [ 0x00 , 0x01 , 0x00 , 0x00 ] ) ] ) ;
3535// Expected stdout for oversizedLengthHeader: first byte is emitted via
3636// String.fromCharCode (byte-by-byte fallback in #drainRawBuffer), remaining
3737// bytes go through the nonSerialized UTF-8 decode path in #processRawBuffer.
3838const oversizedLengthStdout = String . fromCharCode ( oversizedLengthHeader [ 0 ] ) +
3939 Buffer . from ( oversizedLengthHeader . subarray ( 1 ) ) . toString ( 'utf-8' ) ;
4040const unsignedOversizedLengthStdout = String . fromCharCode ( unsignedOversizedLengthHeader [ 0 ] ) +
4141 Buffer . from ( unsignedOversizedLengthHeader . subarray ( 1 ) ) . toString ( 'utf-8' ) ;
42- // FF 0F followed by a small, plausible size (8) and 8 payload bytes. Unlike the
42+ function payloadSize ( size ) {
43+ const buffer = Buffer . alloc ( 4 ) ;
44+ buffer . writeUInt32BE ( size ) ;
45+ return buffer ;
46+ }
47+ // The v8 header followed by a small, plausible size (8) and 8 payload bytes. Unlike the
4348// oversized headers above, this passes the size check, but its payload does not
4449// begin with the inner v8 header a real frame carries, so it is treated as
4550// stdout instead of reaching the deserializer.
4651// Regression fixture for https://github.com/nodejs/node/issues/66164
47- const plausibleSizeFalseHeader = Buffer . from ( [
48- 0xff , 0x0f , // V8 serializer header magic
49- 0x00 , 0x00 , 0x00 , 0x08 , // Payload size of 8 bytes
50- 0x41 , 0x42 , 0x43 , 0x44 , 0x45 , 0x46 , 0x47 , 0x48 , // "ABCDEFGH", not a real payload
52+ const plausibleSizeFalseHeader = Buffer . concat ( [
53+ headerOnly ,
54+ payloadSize ( 8 ) ,
55+ Buffer . from ( 'ABCDEFGH' ) , // Not a real payload
5156] ) ;
5257const plausibleSizeFalseHeaderStdout = String . fromCharCode ( plausibleSizeFalseHeader [ 0 ] ) +
5358 Buffer . from ( plausibleSizeFalseHeader . subarray ( 1 ) ) . toString ( 'utf-8' ) ;
54- // FF 0F , a valid size, then the inner v8 header a real frame repeats, followed
59+ // The v8 header , a valid size, then the inner v8 header a real frame repeats, followed
5560// by a byte that is not a valid serialized value. This passes the inner header
5661// check and reaches the deserializer, which throws. This is what a genuine
5762// report-protocol regression looks like, so the parser must let the error
5863// surface instead of hiding it as stdout.
59- const headeredCorruptFrame = Buffer . from ( [
60- 0xff , 0x0f , // Outer v8 serializer header magic
61- 0x00 , 0x00 , 0x00 , 0x03 , // Payload size of 3 bytes
62- 0xff , 0x0f , // Inner v8 header that a real frame repeats
63- 0xee , // Not a valid serialized value
64+ const headeredCorruptFrame = Buffer . concat ( [
65+ headerOnly ,
66+ payloadSize ( headerLength + 1 ) ,
67+ headerOnly ,
68+ Buffer . from ( [ 0xee ] ) , // Not a valid serialized value
6469] ) ;
65- // FF 0F with a declared size of 1, then more header bytes. The payload is
70+ // The v8 header with a declared size of 1, then more header bytes. The payload is
6671// shorter than the inner v8 header a real frame carries, so it can never be a
6772// real frame. The length guard must reject it as stdout without reaching the
6873// deserializer.
69- const shortPayloadFalseHeader = Buffer . from ( [
70- 0xff , 0x0f , // Outer v8 serializer header magic
71- 0x00 , 0x00 , 0x00 , 0x01 , // Payload size of 1 byte, too short for a header
72- 0xff , 0x0f , // Trailing bytes that also look like a header
74+ const shortPayloadFalseHeader = Buffer . concat ( [
75+ headerOnly ,
76+ payloadSize ( 1 ) ,
77+ headerOnly , // Trailing bytes that also look like a header
7378] ) ;
7479
7580function collectStdout ( reported ) {
@@ -144,10 +149,10 @@ describe('v8 deserializer', common.mustCall(() => {
144149
145150 it ( 'should not hang when buffer starts with v8Header followed by oversized length' , async ( ) => {
146151 // Regression test for https://github.com/nodejs/node/issues/62693
147- // FF 0F is the v8 serializer header; the next 4 bytes are read as a
148- // big-endian message size. 0x7FFFFFFF far exceeds any actual buffer
149- // size, causing #processRawBuffer to make no progress and
150- // #drainRawBuffer to loop forever without the no-progress guard.
152+ // The v8 serializer header is followed by 4 bytes read as a big-endian
153+ // message size. 0x7FFFFFFF far exceeds any actual buffer size, causing
154+ // #processRawBuffer to make no progress and #drainRawBuffer to loop
155+ // forever without the no-progress guard.
151156 const reported = await collectReported ( [ oversizedLengthHeader ] ) ;
152157 assert . partialDeepStrictEqual (
153158 reported ,
@@ -173,14 +178,14 @@ describe('v8 deserializer', common.mustCall(() => {
173178 } ) ;
174179
175180 it ( 'should flush v8Header-only bytes as stdout when stream ends' , async ( ) => {
176- // Just the two-byte v8 header with no size field at all.
181+ // Just the v8 header bytes with no size field at all.
177182 const reported = await collectReported ( [ headerOnly ] ) ;
178183 assert ( reported . every ( ( event ) => event . type === 'test:stdout' ) ) ;
179184 assert . strictEqual ( collectStdout ( reported ) , headerOnly . toString ( 'latin1' ) ) ;
180185 } ) ;
181186
182187 it ( 'should resync and parse valid messages after false v8 header' , async ( ) => {
183- // A false v8 header (FF 0F + oversized length) followed by a
188+ // A false v8 header (header bytes + oversized length) followed by a
184189 // legitimate serialized message. The parser must skip the corrupt
185190 // bytes and still deserialize the real message.
186191 const reported = await collectReported ( [
0 commit comments