1'use strict'; 2// Run this program with valgrind or efence with --expose_gc to expose the 3// problem. 4 5// Flags: --expose_gc 6 7require('../common'); 8const assert = require('assert'); 9const { HTTPParser } = require('_http_common'); 10 11const kOnHeaders = HTTPParser.kOnHeaders | 0; 12const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0; 13const kOnBody = HTTPParser.kOnBody | 0; 14const kOnMessageComplete = HTTPParser.kOnMessageComplete | 0; 15 16let headersComplete = 0; 17let messagesComplete = 0; 18 19function flushPool() { 20 Buffer.allocUnsafe(Buffer.poolSize - 1); 21 global.gc(); 22} 23 24function demoBug(part1, part2) { 25 flushPool(); 26 27 const parser = new HTTPParser(); 28 parser.initialize(HTTPParser.REQUEST, {}); 29 30 parser.headers = []; 31 parser.url = ''; 32 33 parser[kOnHeaders] = function(headers, url) { 34 parser.headers = parser.headers.concat(headers); 35 parser.url += url; 36 }; 37 38 parser[kOnHeadersComplete] = function(info) { 39 headersComplete++; 40 console.log('url', info.url); 41 }; 42 43 parser[kOnBody] = () => {}; 44 45 parser[kOnMessageComplete] = function() { 46 messagesComplete++; 47 }; 48 49 50 // We use a function to eliminate references to the Buffer b 51 // We want b to be GCed. The parser will hold a bad reference to it. 52 (function() { 53 const b = Buffer.from(part1); 54 flushPool(); 55 56 console.log('parse the first part of the message'); 57 parser.execute(b, 0, b.length); 58 })(); 59 60 flushPool(); 61 62 (function() { 63 const b = Buffer.from(part2); 64 65 console.log('parse the second part of the message'); 66 parser.execute(b, 0, b.length); 67 parser.finish(); 68 })(); 69 70 flushPool(); 71} 72 73 74demoBug('POST /1', '/22 HTTP/1.1\r\n' + 75 'Content-Type: text/plain\r\n' + 76 'Content-Length: 4\r\n\r\n' + 77 'pong'); 78 79demoBug('POST /1/22 HTTP/1.1\r\n' + 80 'Content-Type: tex', 't/plain\r\n' + 81 'Content-Length: 4\r\n\r\n' + 82 'pong'); 83 84process.on('exit', function() { 85 assert.strictEqual(headersComplete, 2); 86 assert.strictEqual(messagesComplete, 2); 87 console.log('done!'); 88}); 89