Skip to content

Commit 2462602

Browse files
committed
Assert on struct size when unpacking
To catch protocol errors earlier.
1 parent 5013c8c commit 2462602

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

src/v1/internal/packstream-v1.js

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919
import utf8 from './utf8';
2020
import Integer, {int, isInt} from '../integer';
21-
import {newError} from './../error';
21+
import {newError, PROTOCOL_ERROR} from './../error';
2222
import {Chunker} from './chunking';
2323
import {Node, Path, PathSegment, Relationship, UnboundRelationship} from '../graph-types';
2424

@@ -50,9 +50,16 @@ const STRUCT_8 = 0xDC;
5050
const STRUCT_16 = 0xDD;
5151

5252
const NODE = 0x4E;
53+
const NODE_STRUCT_SIZE = 3;
54+
5355
const RELATIONSHIP = 0x52;
56+
const RELATIONSHIP_STRUCT_SIZE = 5;
57+
5458
const UNBOUND_RELATIONSHIP = 0x72;
59+
const UNBOUND_RELATIONSHIP_STRUCT_SIZE = 3;
60+
5561
const PATH = 0x50;
62+
const PATH_STRUCT_SIZE = 3;
5663

5764
/**
5865
* A Structure have a signature and fields.
@@ -505,30 +512,34 @@ class Unpacker {
505512
}
506513
}
507514

508-
_unpackStructWithSize(size, buffer) {
515+
_unpackStructWithSize(structSize, buffer) {
509516
const signature = buffer.readUInt8();
510517
if (signature == NODE) {
511-
return this._unpackNode(buffer);
518+
return this._unpackNode(structSize, buffer);
512519
} else if (signature == RELATIONSHIP) {
513-
return this._unpackRelationship(buffer);
520+
return this._unpackRelationship(structSize, buffer);
514521
} else if (signature == UNBOUND_RELATIONSHIP) {
515-
return this._unpackUnboundRelationship(buffer);
522+
return this._unpackUnboundRelationship(structSize, buffer);
516523
} else if (signature == PATH) {
517-
return this._unpackPath(buffer);
524+
return this._unpackPath(structSize, buffer);
518525
} else {
519-
return this._unpackUnknownStruct(signature, size, buffer);
526+
return this._unpackUnknownStruct(signature, structSize, buffer);
520527
}
521528
}
522529

523-
_unpackNode(buffer) {
530+
_unpackNode(structSize, buffer) {
531+
this._verifyStructSize('Node', NODE_STRUCT_SIZE, structSize);
532+
524533
return new Node(
525534
this.unpack(buffer), // Identity
526535
this.unpack(buffer), // Labels
527536
this.unpack(buffer) // Properties
528537
);
529538
}
530539

531-
_unpackRelationship(buffer) {
540+
_unpackRelationship(structSize, buffer) {
541+
this._verifyStructSize('Relationship', RELATIONSHIP_STRUCT_SIZE, structSize);
542+
532543
return new Relationship(
533544
this.unpack(buffer), // Identity
534545
this.unpack(buffer), // Start Node Identity
@@ -538,15 +549,19 @@ class Unpacker {
538549
);
539550
}
540551

541-
_unpackUnboundRelationship(buffer) {
552+
_unpackUnboundRelationship(structSize, buffer) {
553+
this._verifyStructSize('UnboundRelationship', UNBOUND_RELATIONSHIP_STRUCT_SIZE, structSize);
554+
542555
return new UnboundRelationship(
543556
this.unpack(buffer), // Identity
544557
this.unpack(buffer), // Type
545558
this.unpack(buffer) // Properties
546559
);
547560
}
548561

549-
_unpackPath(buffer) {
562+
_unpackPath(structSize, buffer) {
563+
this._verifyStructSize('Path', PATH_STRUCT_SIZE, structSize);
564+
550565
const nodes = this.unpack(buffer);
551566
const rels = this.unpack(buffer);
552567
const sequence = this.unpack(buffer);
@@ -582,14 +597,19 @@ class Unpacker {
582597
return new Path(nodes[0], nodes[nodes.length - 1], segments);
583598
}
584599

585-
_unpackUnknownStruct(signature, size, buffer) {
600+
_unpackUnknownStruct(signature, structSize, buffer) {
586601
const result = new Structure(signature, []);
587-
for (let i = 0; i < size; i++) {
602+
for (let i = 0; i < structSize; i++) {
588603
result.fields.push(this.unpack(buffer));
589604
}
590605
return result;
591606
}
592607

608+
_verifyStructSize(structName, expectedSize, actualSize) {
609+
if (expectedSize !== actualSize) {
610+
throw newError(`Wrong struct size for ${structName}, expected ${expectedSize} but was ${actualSize}`, PROTOCOL_ERROR);
611+
}
612+
}
593613
}
594614

595615
export {

src/v1/internal/packstream-v2.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ import {isPoint, Point} from '../spatial-types';
2222
import {int} from '../integer';
2323

2424
const POINT_2D = 0x58;
25+
const POINT_2D_STRUCT_SIZE = 3;
26+
2527
const POINT_3D = 0x59;
28+
const POINT_3D_STRUCT_SIZE = 4;
2629

2730
export class Packer extends v1.Packer {
2831

@@ -58,13 +61,13 @@ export class Unpacker extends v1.Unpacker {
5861
}
5962

6063

61-
_unpackUnknownStruct(signature, size, buffer) {
64+
_unpackUnknownStruct(signature, structSize, buffer) {
6265
if (signature == POINT_2D) {
63-
return unpackPoint2D(this, buffer);
66+
return unpackPoint2D(this, structSize, buffer);
6467
} else if (signature == POINT_3D) {
65-
return unpackPoint3D(this, buffer);
68+
return unpackPoint3D(this, structSize, buffer);
6669
} else {
67-
return super._unpackUnknownStruct(signature, size, buffer);
70+
return super._unpackUnknownStruct(signature, structSize, buffer);
6871
}
6972
}
7073
}
@@ -97,7 +100,9 @@ function packPoint3D(point, packer, onError) {
97100
packer.packStruct(POINT_3D, packableStructFields, onError);
98101
}
99102

100-
function unpackPoint2D(unpacker, buffer) {
103+
function unpackPoint2D(unpacker, structSize, buffer) {
104+
unpacker._verifyStructSize('Point2D', POINT_2D_STRUCT_SIZE, structSize);
105+
101106
return new Point(
102107
unpacker.unpack(buffer), // srid
103108
unpacker.unpack(buffer), // x
@@ -106,7 +111,9 @@ function unpackPoint2D(unpacker, buffer) {
106111
);
107112
}
108113

109-
function unpackPoint3D(unpacker, buffer) {
114+
function unpackPoint3D(unpacker, structSize, buffer) {
115+
unpacker._verifyStructSize('Point3D', POINT_3D_STRUCT_SIZE, structSize);
116+
110117
return new Point(
111118
unpacker.unpack(buffer), // srid
112119
unpacker.unpack(buffer), // x

0 commit comments

Comments
 (0)