[Pkg-javascript-commits] [node-asn1.js] 15/202: encoder: even better error reporting

Bastien Roucariès rouca at moszumanska.debian.org
Thu Apr 20 19:18:50 UTC 2017


This is an automated email from the git hooks/post-receive script.

rouca pushed a commit to branch master
in repository node-asn1.js.

commit a93e79b3d762119319b0a8146e6be217c7ad143d
Author: Fedor Indutny <fedor.indutny at gmail.com>
Date:   Sun Dec 1 23:48:29 2013 +0400

    encoder: even better error reporting
---
 lib/asn1/api.js           |  4 +--
 lib/asn1/base/error.js    | 13 ++++++++
 lib/asn1/base/index.js    |  1 +
 lib/asn1/base/node.js     | 19 +++++++----
 lib/asn1/encoders/der.js  | 15 +++++----
 test/encode-error-test.js | 82 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 120 insertions(+), 14 deletions(-)

diff --git a/lib/asn1/api.js b/lib/asn1/api.js
index f154ff3..0d40b68 100644
--- a/lib/asn1/api.js
+++ b/lib/asn1/api.js
@@ -35,9 +35,9 @@ Entity.prototype.decode = function decode(data, enc) {
   return this.decoders[enc].decode(data);
 };
 
-Entity.prototype.encode = function encode(data, enc) {
+Entity.prototype.encode = function encode(data, enc, /* internal */ path) {
   // Lazily create encoder
   if (!this.encoders.hasOwnProperty(enc))
     this.encoders[enc] = this._createNamed(asn1.encoders[enc]);
-  return this.encoders[enc].encode(data);
+  return this.encoders[enc].encode(data, path);
 };
diff --git a/lib/asn1/base/error.js b/lib/asn1/base/error.js
new file mode 100644
index 0000000..83f5985
--- /dev/null
+++ b/lib/asn1/base/error.js
@@ -0,0 +1,13 @@
+var util = require('util');
+
+function EncoderError(path, original) {
+  var message = 'Encoder error at object path: ' +
+                JSON.stringify(path) +
+                '\n';
+  Error.call(this, message + original.message);
+
+  this.stack = message + original.stack;
+};
+util.inherits(EncoderError, Error);
+
+exports.EncoderError = EncoderError;
diff --git a/lib/asn1/base/index.js b/lib/asn1/base/index.js
index a46492c..4ba01f8 100644
--- a/lib/asn1/base/index.js
+++ b/lib/asn1/base/index.js
@@ -1,5 +1,6 @@
 var base = exports;
 
+base.EncoderError = require('./error').EncoderError;
 base.DecoderBuffer = require('./buffer').DecoderBuffer;
 base.EncoderBuffer = require('./buffer').EncoderBuffer;
 base.Node = require('./node');
diff --git a/lib/asn1/base/node.js b/lib/asn1/base/node.js
index e2a7dff..db6a571 100644
--- a/lib/asn1/base/node.js
+++ b/lib/asn1/base/node.js
@@ -1,5 +1,6 @@
 var assert = require('assert');
 var EncoderBuffer = require('../base').EncoderBuffer;
+var EncoderError = require('../base').EncoderError;
 
 // Supported tags
 var tags = [
@@ -365,7 +366,7 @@ Node.prototype._encode = function encode(data, path) {
 
   // Decode root node
   if (state.parent === null)
-    return state.children[0]._encode(data, '');
+    return state.children[0]._encode(data, path || '');
 
   var result = null;
   var present = true;
@@ -386,12 +387,18 @@ Node.prototype._encode = function encode(data, path) {
     result = new EncoderBuffer(data);
   } else if (state.children) {
     content = state.children.map(function(child) {
-      assert(child._baseState.key, 'Child should have a key');
-      var newpath = path + '.' + child._baseState.key;
+      assert(child._baseState.key !== null, 'Child should have a key');
+
+      // Maintain path for error reporting purposes
+      var newpath = path ? path + '.' + child._baseState.key :
+                           child._baseState.key;
       try {
         return child._encode(data[child._baseState.key], newpath);
       } catch (e) {
-        throw new Error('Failed to encode: ' + newpath + '\n' + e.stack);
+        if (e instanceof EncoderError)
+          throw e;
+        else
+          throw new EncoderError(newpath, e);
       }
     }, this).filter(function(child) {
       return child;
@@ -405,10 +412,10 @@ Node.prototype._encode = function encode(data, path) {
         assert(Array.isArray(data), 'seqof/setof, but data is not Array');
 
         content = new EncoderBuffer(data.map(function(item) {
-          return this._use(state.args[0], item);
+          return this._use(state.args[0], item, path);
         }, this));
       } else if (state.use !== null) {
-        result = this._use(state.use, data);
+        result = this._use(state.use, data, path);
       } else {
         content = this._encodePrimitive(state.tag, data);
         primitive = true;
diff --git a/lib/asn1/encoders/der.js b/lib/asn1/encoders/der.js
index 54b4b8b..243977a 100644
--- a/lib/asn1/encoders/der.js
+++ b/lib/asn1/encoders/der.js
@@ -19,8 +19,8 @@ function DEREncoder(entity) {
 };
 module.exports = DEREncoder;
 
-DEREncoder.prototype.encode = function encode(data) {
-  return this.tree._encode(data).join();
+DEREncoder.prototype.encode = function encode(data, path) {
+  return this.tree._encode(data, path).join();
 };
 
 // Tree methods
@@ -77,7 +77,9 @@ DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) {
       id[i] |= 0;
   }
 
-  assert(Array.isArray(id));
+  assert(Array.isArray(id),
+         'objid() should be either array or string, got: ' +
+              JSON.stringify(id));
   if (!relative) {
     assert(id[1] < 40, 'Second objid identifier OOB');
     id.splice(0, 2, id[0] * 40 + id[1]);
@@ -148,7 +150,8 @@ DERNode.prototype._encodeNull = function encodeNull() {
 DERNode.prototype._encodeInt = function encodeInt(num, values) {
   if (typeof num === 'string') {
     assert(values, 'String int or enum given, but no values map');
-    assert(values.hasOwnProperty(num), 'Values map doesn\'t contain number');
+    assert(values.hasOwnProperty(num),
+           'Values map doesn\'t contain: ' + JSON.stringify(num));
     num = values[num];
   }
 
@@ -172,8 +175,8 @@ DERNode.prototype._encodeBool = function encodeBool(value) {
   return new base.EncoderBuffer(value ? 0xff : 0);
 };
 
-DERNode.prototype._use = function use(encoder, data) {
-  return encoder.encode(data, 'der');
+DERNode.prototype._use = function use(encoder, data, path) {
+  return encoder.encode(data, 'der', path);
 };
 
 // Utility methods
diff --git a/test/encode-error-test.js b/test/encode-error-test.js
new file mode 100644
index 0000000..113805d
--- /dev/null
+++ b/test/encode-error-test.js
@@ -0,0 +1,82 @@
+var assert = require('assert');
+var asn1 = require('..');
+
+var Buffer = require('buffer').Buffer;
+
+describe('asn1.js encode error', function() {
+  function test(name, model, input, expected) {
+    it('should support ' + name, function() {
+      var M = asn1.define('TestModel', model);
+
+      var error;
+      assert.throws(function() {
+        try {
+          var encoded = M.encode(input, 'der');
+        } catch (e) {
+          error = e;
+          throw e;
+        }
+      });
+
+      assert(expected.test(error.stack),
+             'Failed to match, expected: ' + expected + ' got: ' +
+                 JSON.stringify(error.stack));
+    });
+  }
+
+  describe('primitives', function() {
+    test('int', function() {
+      this.int();
+    }, 'hello', /no values map/i);
+
+    test('enum', function() {
+      this.enum({ 0: 'hello', 1: 'world' });
+    }, 'gosh', /contain: "gosh"/);
+
+    test('objid', function() {
+      this.objid();
+    }, 1, /objid\(\) should be either array or string, got: 1/);
+  });
+
+  describe('composite', function() {
+    test('shallow', function() {
+      this.seq().obj(
+        this.key('key').int()
+      );
+    }, { key: 'hello' } , /object path: "key"/i);
+
+    test('deep and empty', function() {
+      this.seq().obj(
+        this.key('a').seq().obj(
+          this.key('b').seq().obj(
+            this.key('c').int()
+          )
+        )
+      );
+    }, { } , /object path: "a.b"/i);
+
+    test('deep', function() {
+      this.seq().obj(
+        this.key('a').seq().obj(
+          this.key('b').seq().obj(
+            this.key('c').int()
+          )
+        )
+      );
+    }, { a: { b: { c: 'hello' } } } , /object path: "a.b.c"/i);
+
+    test('use', function() {
+      var S = asn1.define('S', function() {
+        this.seq().obj(
+          this.key('x').int()
+        );
+      });
+
+      this.seq().obj(
+        this.key('a').seq().obj(
+          this.key('b').use(S)
+        )
+      );
+    }, { a: { b: { x: 'hello' } } } , /object path: "a.b.x"/i);
+  });
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-asn1.js.git



More information about the Pkg-javascript-commits mailing list