[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