diff --git a/test/simple/test-http-parser-bad-ref.js b/test/simple/test-http-parser-bad-ref.js new file mode 100644 index 00000000000..b8fd5b2917a --- /dev/null +++ b/test/simple/test-http-parser-bad-ref.js @@ -0,0 +1,72 @@ +// Run this program with valgrind or efence with --expose_gc to expose the +// problem. + +// Flags: --expose_gc + +var assert = require('assert'); +var HTTPParser = process.binding('http_parser').HTTPParser; + +var headersComplete = 0; +var messagesComplete = 0; + +function flushPool() { + new Buffer(Buffer.poolSize - 1); + gc(); +} + +function demoBug(part1, part2) { + var parser = new HTTPParser('REQUEST'); + + parser.headers = []; + parser.url = ''; + + parser.onHeaders = function(headers, url) { + parser.headers = parser.headers.concat(headers); + parser.url += url; + }; + + parser.onHeadersComplete = function(info) { + headersComplete++; + console.log("url", info.url); + }; + + parser.onBody = function(b, start, len) { }; + + parser.onMessageComplete = function() { + messagesComplete++; + }; + + + // We use a function to eliminate references to the Buffer b + // We want b to be GCed. The parser will hold a bad reference to it. + (function() { + var b = Buffer(part1); + flushPool(); + + console.log("parse the first part of the message"); + parser.execute(b, 0, b.length); + })(); + + flushPool(); + + (function() { + var b = Buffer(part2); + + console.log("parse the second part of the message"); + parser.execute(b, 0, b.length); + parser.finish(); + })(); +} + + +demoBug('POST /1', '/22 HTTP/1.1\r\n' + + 'Content-Type: text/plain\r\n' + + 'Content-Length: 4\r\n\r\n' + + 'pong'); + + +process.on('exit', function() { + assert.equal(1, headersComplete); + assert.equal(1, messagesComplete); + console.log("done!"); +});