Repository: tediousjs/node-mssql
Pull request #1138 (2020-11-18 22:37:01)

fix geography v2 parsing #322
fix for #322

Geography parsing would crash on geography version 2 when there is no segment.
According to [the v2 spec](https://docs.microsoft.com/en-us/openspecs/sql_server_protocols/ms-ssclrt/35a20944-9c83-4776-91c6-b5f5af5fef03), the number of segments-bytes are optional, so we have to check the input length.

I've added unit tests to demonstrate the issue.

dhensby: Amazing, thanks for this - I think I'll target this at v6 so we can get a stable out and then merge it up into the v7 branch (master).

Patch:
diff --git a/lib/udt.js b/lib/udt.js
index a694271..761f002 100644
--- a/lib/udt.js
+++ b/lib/udt.js
@@ -271,7 +271,7 @@ const parseGeography = buffer => {
 
   // console.log( "shapes", shapes)
 
-  if (value.version === 2) {
+  if (value.version === 2 && buffer.position < buffer.length) {
     const numberOfSegments = buffer.readUInt32LE(buffer.position)
     buffer.position += 4
 


Test patch:
diff --git a/test/common/unit.js b/test/common/unit.js
index 453288c..70ab85c 100644
--- a/test/common/unit.js
+++ b/test/common/unit.js
@@ -5,6 +5,7 @@
 const sql = require('../../')
 const assert = require('assert')
 const cs = require('../../lib/connectionstring')
+const udt = require('../../lib/udt')
 
 describe('Connection String', () => {
   it('Connection String #1', done => {
@@ -286,3 +287,41 @@ describe('Unit', () => {
     assert.strictEqual(req.parameters.param1.value, 123)
   })
 })
+
+describe('Geography Parsing', () => {
+  it('polygon v1', () => {
+    // select geography::STGeomFromText(N'POLYGON((1 1, 3 1, 3 7, 1 1))',4326)
+    const buffer = Buffer.from('E6100000010404000000000000000000F03F000000000000F03F000000000000F03F00000000000008400000000000001C400000000000000840000000000000F03F000000000000F03F01000000020000000001000000FFFFFFFF0000000003', 'hex')
+    const geo = udt.PARSERS.geography(buffer)
+
+    assert.strictEqual(geo.version, 1)
+    assert.strictEqual(geo.srid, 4326)
+    assert.strictEqual(geo.points.length, 4)
+    assert.strictEqual(geo.points[0].y, 1)
+    assert.strictEqual(geo.points[0].x, 1)
+    assert.strictEqual(geo.points[1].y, 3)
+    assert.strictEqual(geo.points[1].x, 1)
+    assert.strictEqual(geo.points[2].y, 3)
+    assert.strictEqual(geo.points[2].x, 7)
+    assert.strictEqual(geo.points[3].y, 1)
+    assert.strictEqual(geo.points[3].x, 1)
+  })
+
+  it('polygon v2', () => {
+    // select geography::STGeomFromText(N'POLYGON((1 1, 3 1, 3 1, 1 1))',4326)
+    const buffer = Buffer.from('E6100000020004000000000000000000F03F000000000000F03F000000000000F03F0000000000000840000000000000F03F0000000000000840000000000000F03F000000000000F03F01000000010000000001000000FFFFFFFF0000000003', 'hex')
+    const geo = udt.PARSERS.geography(buffer)
+
+    assert.strictEqual(geo.version, 2)
+    assert.strictEqual(geo.srid, 4326)
+    assert.strictEqual(geo.points.length, 4)
+    assert.strictEqual(geo.points[0].y, 1)
+    assert.strictEqual(geo.points[0].x, 1)
+    assert.strictEqual(geo.points[1].y, 3)
+    assert.strictEqual(geo.points[1].x, 1)
+    assert.strictEqual(geo.points[2].y, 3)
+    assert.strictEqual(geo.points[2].x, 1)
+    assert.strictEqual(geo.points[3].y, 1)
+    assert.strictEqual(geo.points[3].x, 1)
+  })
+})