@@ -40,16 +40,28 @@ const oversizedLengthStdout = String.fromCharCode(oversizedLengthHeader[0]) +
4040const unsignedOversizedLengthStdout = String . fromCharCode ( unsignedOversizedLengthHeader [ 0 ] ) +
4141 Buffer . from ( unsignedOversizedLengthHeader . subarray ( 1 ) ) . toString ( 'utf-8' ) ;
4242// FF 0F followed by a small, plausible size (8) and 8 payload bytes. Unlike the
43- // oversized headers above, this passes the size check and reaches the
44- // deserializer, which throws because the payload is not a real message.
43+ // oversized headers above, this passes the size check, but its payload does not
44+ // begin with the inner v8 header a real frame carries, so it is treated as
45+ // stdout instead of reaching the deserializer.
4546// Regression fixture for https://github.com/nodejs/node/issues/66164
4647const plausibleSizeFalseHeader = Buffer . from ( [
47- 0xff , 0x0f , // v8 serializer header magic
48- 0x00 , 0x00 , 0x00 , 0x08 , // payload size of 8 bytes
48+ 0xff , 0x0f , // V8 serializer header magic
49+ 0x00 , 0x00 , 0x00 , 0x08 , // Payload size of 8 bytes
4950 0x41 , 0x42 , 0x43 , 0x44 , 0x45 , 0x46 , 0x47 , 0x48 , // "ABCDEFGH", not a real payload
5051] ) ;
5152const plausibleSizeFalseHeaderStdout = String . fromCharCode ( plausibleSizeFalseHeader [ 0 ] ) +
5253 Buffer . from ( plausibleSizeFalseHeader . subarray ( 1 ) ) . toString ( 'utf-8' ) ;
54+ // FF 0F, a valid size, then the inner v8 header a real frame repeats, followed
55+ // by a byte that is not a valid serialized value. This passes the inner header
56+ // check and reaches the deserializer, which throws. This is what a genuine
57+ // report-protocol regression looks like, so the parser must let the error
58+ // 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+ ] ) ;
5365
5466function collectStdout ( reported ) {
5567 return reported
@@ -182,16 +194,17 @@ describe('v8 deserializer', common.mustCall(() => {
182194
183195 it ( 'should not crash when stdout mimics a v8 frame with a plausible size' , async ( ) => {
184196 // Regression test for https://github.com/nodejs/node/issues/66164
185- // The bytes reach the deserializer and it throws. The parser must emit
186- // them as stdout instead of letting the error abort the whole run.
197+ // The payload does not start with the inner v8 header that a real frame
198+ // carries, so the parser treats the bytes as stdout instead of handing
199+ // them to the deserializer and aborting the whole run.
187200 const reported = await collectReported ( [ plausibleSizeFalseHeader ] ) ;
188201 assert ( reported . every ( ( event ) => event . type === 'test:stdout' ) ) ;
189202 assert . strictEqual ( collectStdout ( reported ) , plausibleSizeFalseHeaderStdout ) ;
190203 } ) ;
191204
192205 it ( 'should resync and parse a real message after a plausible-size false frame' , async ( ) => {
193206 // The poison bytes followed by a real serialized message. The parser must
194- // recover from the failed deserialize and still report the real event.
207+ // reject the poison as stdout and still report the real event.
195208 const reported = await collectReported ( [
196209 plausibleSizeFalseHeader ,
197210 ...chunks ,
@@ -226,6 +239,14 @@ describe('v8 deserializer', common.mustCall(() => {
226239 assert . strictEqual ( collectStdout ( reported ) , plausibleSizeFalseHeaderStdout ) ;
227240 } ) ;
228241
242+ it ( 'should surface a genuinely corrupt frame instead of hiding it' , ( ) => {
243+ // A frame with both v8 headers and a valid size but an invalid value is
244+ // what a real report-protocol regression looks like, not stray stdout.
245+ // The parser must let the deserialize error surface instead of silently
246+ // turning it into stdout.
247+ assert . throws ( ( ) => fileTest . parseMessage ( headeredCorruptFrame ) , / d e s e r i a l i z e / ) ;
248+ } ) ;
249+
229250 const headerPosition = headerLength * 2 + 4 ;
230251 for ( let i = 0 ; i < headerPosition + 5 ; i ++ ) {
231252 const message = `should deserialize a serialized message split into two chunks {...${ i } ,${ i + 1 } ...}` ;
0 commit comments