http2
Advanced tools
Comparing version 3.3.0 to 3.3.1
Version history | ||
=============== | ||
### 3.3.1 (2016-01-11) ### | ||
* Fix some DoS bugs (issues 145, 146, 147, and 148) | ||
### 3.3.0 (2016-01-10) ### | ||
* Bugfix updates from pull requests | ||
### 3.2.0 (2015-02-19) ### | ||
@@ -5,0 +13,0 @@ |
@@ -671,2 +671,6 @@ // Public API | ||
this.url = this._checkSpecialHeader(':path' , headers[':path'] ); | ||
if (!this.method || !this.scheme || !this.host || !this.url) { | ||
// This is invalid, and we've sent a RST_STREAM, so don't continue processing | ||
return; | ||
} | ||
@@ -673,0 +677,0 @@ // * Host header is included in the headers object for backwards compatibility. |
@@ -356,2 +356,23 @@ var assert = require('assert'); | ||
// Do some sanity checking here before we create a stream | ||
if ((frame.type == 'SETTINGS' || | ||
frame.type == 'PING' || | ||
frame.type == 'GOAWAY') && | ||
frame.stream != 0) { | ||
// Got connection-level frame on a stream - EEP! | ||
this.close('PROTOCOL_ERROR'); | ||
return; | ||
} else if ((frame.type == 'DATA' || | ||
frame.type == 'HEADERS' || | ||
frame.type == 'PRIORITY' || | ||
frame.type == 'RST_STREAM' || | ||
frame.type == 'PUSH_PROMISE' || | ||
frame.type == 'CONTINUATION') && | ||
frame.stream == 0) { | ||
// Got stream-level frame on connection - EEP! | ||
this.close('PROTOCOL_ERROR'); | ||
return; | ||
} | ||
// WINDOW_UPDATE can be on either stream or connection | ||
// * gets the appropriate stream from the stream registry | ||
@@ -362,2 +383,7 @@ var stream = this._streamIds[frame.stream]; | ||
if (!stream) { | ||
if (frame.type != 'HEADERS') { | ||
// HEADERS is the only thing that can create a stream, freak out. | ||
this.close('PROTOCOL_ERROR'); | ||
return; | ||
} | ||
stream = this._createIncomingStream(frame.stream); | ||
@@ -364,0 +390,0 @@ } |
@@ -238,2 +238,6 @@ // The framer consists of two [Transform Stream][1] subclasses that operate in [object mode][2]: | ||
Deserializer.commonHeader = function readCommonHeader(buffer, frame) { | ||
if (buffer.length < 9) { | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
var totallyWastedByte = buffer.readUInt8(0); | ||
@@ -301,2 +305,6 @@ var length = buffer.readUInt16BE(1); | ||
if (frame.flags.PADDED) { | ||
if (buffer.length < 1) { | ||
// We must have at least one byte for padding control, but we don't. Bad peer! | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
paddingLength = (buffer.readUInt8(dataOffset) & 0xff); | ||
@@ -307,2 +315,6 @@ dataOffset = 1; | ||
if (paddingLength) { | ||
if (paddingLength >= (buffer.length - 1)) { | ||
// We don't have enough room for the padding advertised - bad peer! | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
frame.data = buffer.slice(dataOffset, -1 * paddingLength); | ||
@@ -371,2 +383,14 @@ } else { | ||
Deserializer.HEADERS = function readHeadersPriority(buffer, frame) { | ||
var minFrameLength = 0; | ||
if (frame.flags.PADDED) { | ||
minFrameLength += 1; | ||
} | ||
if (frame.flags.PRIORITY) { | ||
minFrameLength += 5; | ||
} | ||
if (buffer.length < minFrameLength) { | ||
// Peer didn't send enough data - bad peer! | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
var dataOffset = 0; | ||
@@ -391,2 +415,6 @@ var paddingLength = 0; | ||
if (paddingLength) { | ||
if ((buffer.length - dataOffset) < paddingLength) { | ||
// Not enough data left to satisfy the advertised padding - bad peer! | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
frame.data = buffer.slice(dataOffset, -1 * paddingLength); | ||
@@ -435,2 +463,6 @@ } else { | ||
Deserializer.PRIORITY = function readPriority(buffer, frame) { | ||
if (buffer.length < 5) { | ||
// PRIORITY frames are 5 bytes long. Bad peer! | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
var dependencyData = new Buffer(4); | ||
@@ -475,2 +507,6 @@ buffer.copy(dependencyData, 0, 0, 4); | ||
Deserializer.RST_STREAM = function readRstStream(buffer, frame) { | ||
if (buffer.length < 4) { | ||
// RST_STREAM is 4 bytes long. Bad peer! | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
frame.error = errorCodes[buffer.readUInt32BE(0)]; | ||
@@ -636,5 +672,11 @@ if (!frame.error) { | ||
Deserializer.PUSH_PROMISE = function readPushPromise(buffer, frame) { | ||
if (buffer.length < 4) { | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
var dataOffset = 0; | ||
var paddingLength = 0; | ||
if (frame.flags.PADDED) { | ||
if (buffer.length < 5) { | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
paddingLength = (buffer.readUInt8(dataOffset) & 0xff); | ||
@@ -646,2 +688,5 @@ dataOffset = 1; | ||
if (paddingLength) { | ||
if ((buffer.length - dataOffset) < paddingLength) { | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
frame.data = buffer.slice(dataOffset, -1 * paddingLength); | ||
@@ -726,2 +771,6 @@ } else { | ||
Deserializer.GOAWAY = function readGoaway(buffer, frame) { | ||
if (buffer.length !== 8) { | ||
// GOAWAY must have 8 bytes | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
frame.last_stream = buffer.readUInt32BE(0) & 0x7fffffff; | ||
@@ -999,3 +1048,9 @@ frame.error = errorCodes[buffer.readUInt32BE(4)]; | ||
Deserializer.ALTSVC = function readAltSvc(buffer, frame) { | ||
if (buffer.length < 2) { | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
var originLength = buffer.readUInt16BE(0); | ||
if ((buffer.length - 2) < originLength) { | ||
return 'FRAME_SIZE_ERROR'; | ||
} | ||
frame.origin = buffer.toString('ascii', 2, 2 + originLength); | ||
@@ -1002,0 +1057,0 @@ var fieldValue = buffer.toString('ascii', 2 + originLength); |
{ | ||
"name": "http2", | ||
"version": "3.3.0", | ||
"version": "3.3.1", | ||
"description": "An HTTP/2 client and server implementation", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
321129
7635