[Pkg-javascript-commits] [node-asn1.js] 23/202: lib: refactor 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 700d2b5c2c90bd309413713123c56591e62cf71f
Author: Fedor Indutny <fedor.indutny at gmail.com>
Date:   Sat Dec 7 16:43:47 2013 +0400

    lib: refactor error reporting
---
 lib/asn1/api.js           |   4 +-
 lib/asn1/base/buffer.js   |  32 ++++++++++----
 lib/asn1/base/error.js    |  13 ------
 lib/asn1/base/index.js    |   2 +-
 lib/asn1/base/node.js     | 107 +++++++++++++++++++++++++++-------------------
 lib/asn1/base/reporter.js |  75 ++++++++++++++++++++++++++++++++
 lib/asn1/decoders/der.js  |  93 +++++++++++++++++++++++++++++-----------
 lib/asn1/encoders/der.js  |  68 ++++++++++++++++-------------
 test/encode-error-test.js |   8 ++--
 9 files changed, 273 insertions(+), 129 deletions(-)

diff --git a/lib/asn1/api.js b/lib/asn1/api.js
index 0d40b68..5812982 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, /* internal */ path) {
+Entity.prototype.encode = function encode(data, enc, /* internal */ reporter) {
   // Lazily create encoder
   if (!this.encoders.hasOwnProperty(enc))
     this.encoders[enc] = this._createNamed(asn1.encoders[enc]);
-  return this.encoders[enc].encode(data, path);
+  return this.encoders[enc].encode(data, reporter);
 };
diff --git a/lib/asn1/base/buffer.js b/lib/asn1/base/buffer.js
index 30d9a8d..578dbbb 100644
--- a/lib/asn1/base/buffer.js
+++ b/lib/asn1/base/buffer.js
@@ -1,13 +1,20 @@
 var assert = require('assert');
+var util = require('util');
+var Reporter = require('../base').Reporter;
 var Buffer = require('buffer').Buffer;
 
-function DecoderBuffer(base) {
-  assert(Buffer.isBuffer(base));
+function DecoderBuffer(base, options) {
+  Reporter.call(this, options);
+  if (!Buffer.isBuffer(base)) {
+    this.error('Input not Buffer');
+    return;
+  }
 
   this.base = base;
   this.offset = 0;
   this.length = base.length;
 }
+util.inherits(DecoderBuffer, Reporter);
 exports.DecoderBuffer = DecoderBuffer;
 
 DecoderBuffer.prototype.save = function save() {
@@ -30,13 +37,21 @@ DecoderBuffer.prototype.isEmpty = function isEmpty() {
 };
 
 DecoderBuffer.prototype.readUInt8 = function readUInt8() {
-  assert(this.offset + 1 <= this.length);
-  return this.base.readUInt8(this.offset++, true);
+  if (this.offset + 1 <= this.length)
+    return this.base.readUInt8(this.offset++, true);
+  else
+    return this.error('DecoderBuffer overrun');
 }
 
 DecoderBuffer.prototype.skip = function skip(bytes) {
-  assert(this.offset + bytes <= this.length);
+  if (!(this.offset + bytes <= this.length))
+    return this.error('DecoderBuffer overrun');
+
   var res = new DecoderBuffer(this.base);
+
+  // Share reporter state
+  res._reporterState = this._reporterState;
+
   res.offset = this.offset;
   res.length = this.offset + bytes;
   this.offset += bytes;
@@ -47,7 +62,7 @@ DecoderBuffer.prototype.raw = function raw() {
   return this.base.slice(this.offset, this.length);
 }
 
-function EncoderBuffer(value) {
+function EncoderBuffer(value, reporter) {
   if (Array.isArray(value)) {
     this.length = 0;
     this.value = value.map(function(item) {
@@ -57,7 +72,8 @@ function EncoderBuffer(value) {
       return item;
     }, this);
   } else if (typeof value === 'number') {
-    assert(0 <= value && value <= 0xff, 'non-byte EncoderBuffer value');
+    if (!(0 <= value && value <= 0xff))
+      return reporter.error('non-byte EncoderBuffer value');
     this.value = value;
     this.length = 1;
   } else if (typeof value === 'string') {
@@ -67,7 +83,7 @@ function EncoderBuffer(value) {
     this.value = value;
     this.length = value.length;
   } else {
-    assert(0, 'Unsupported type: ' + typeof value);
+    return reporter.error('Unsupporter type: ' + typeof value);
   }
 }
 exports.EncoderBuffer = EncoderBuffer;
diff --git a/lib/asn1/base/error.js b/lib/asn1/base/error.js
deleted file mode 100644
index 83f5985..0000000
--- a/lib/asn1/base/error.js
+++ /dev/null
@@ -1,13 +0,0 @@
-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 4ba01f8..935abde 100644
--- a/lib/asn1/base/index.js
+++ b/lib/asn1/base/index.js
@@ -1,6 +1,6 @@
 var base = exports;
 
-base.EncoderError = require('./error').EncoderError;
+base.Reporter = require('./reporter').Reporter;
 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 db6a571..d600d58 100644
--- a/lib/asn1/base/node.js
+++ b/lib/asn1/base/node.js
@@ -1,6 +1,6 @@
 var assert = require('assert');
+var Reporter = require('../base').Reporter;
 var EncoderBuffer = require('../base').EncoderBuffer;
-var EncoderError = require('../base').EncoderError;
 
 // Supported tags
 var tags = [
@@ -237,7 +237,7 @@ Node.prototype.choice = function choice(obj) {
 // Decoding
 //
 
-Node.prototype._decode = function decode(input, obj) {
+Node.prototype._decode = function decode(input) {
   var state = this._baseState;
 
   // Decode root node
@@ -247,6 +247,10 @@ Node.prototype._decode = function decode(input, obj) {
   var result = state['default'];
   var present = true;
 
+  var prevKey;
+  if (state.key !== null)
+    prevKey = input.enterKey(state.key);
+
   // Check if tag is there
   if (state.optional) {
     present = this._peekTag(
@@ -258,10 +262,9 @@ Node.prototype._decode = function decode(input, obj) {
   }
 
   // Push object on stack
-  if (state.obj && present) {
-    var prevObj = obj;
-    obj = {};
-  }
+  var prevObj;
+  if (state.obj && present)
+    prevObj = input.enterObject();
 
   if (present) {
     // Unwrap explicit values
@@ -283,25 +286,23 @@ Node.prototype._decode = function decode(input, obj) {
     else if (state.choice === null)
       result = this._decodeGeneric(state.tag, input);
     else
-      result = this._decodeChoice(input, obj);
+      result = this._decodeChoice(input);
 
     // Decode children
     if (!state.any && state.choice === null && state.children !== null) {
       state.children.forEach(function decodeChildren(child) {
-        child._decode(input, obj);
+        child._decode(input);
       });
     }
   }
 
   // Pop object
-  if (state.obj && present) {
-    result = obj;
-    obj = prevObj;
-  }
+  if (state.obj && present)
+    result = input.leaveObject(prevObj);
 
   // Set key
   if (state.key !== null)
-    obj[state.key] = result;
+    input.leaveKey(prevKey, state.key, result);
 
   return result;
 };
@@ -330,12 +331,12 @@ Node.prototype._decodeGeneric = function decodeGeneric(tag, input) {
   else if (state.use !== null)
     return this._use(input, state.use);
   else
-    assert(false, 'unknown tag: ' + tag);
+    return input.error('unknown tag: ' + tag);
 
   return null;
 };
 
-Node.prototype._decodeChoice = function decodeChoice(input, obj) {
+Node.prototype._decodeChoice = function decodeChoice(input) {
   var state = this._baseState;
   var result = null;
   var match = false;
@@ -344,7 +345,7 @@ Node.prototype._decodeChoice = function decodeChoice(input, obj) {
     var save = input.save();
     var node = state.choice[key];
     try {
-      result = { type: key, value: node._decode(input, obj) };
+      result = { type: key, value: node._decode(input) };
       match = true;
     } catch (e) {
       input.restore(save);
@@ -353,7 +354,9 @@ Node.prototype._decodeChoice = function decodeChoice(input, obj) {
     return true;
   }, this);
 
-  assert(match, 'Choice not matched');
+  if (!match)
+    return input.error('Choice not matched');
+
   return result;
 };
 
@@ -361,16 +364,23 @@ Node.prototype._decodeChoice = function decodeChoice(input, obj) {
 // Encoding
 //
 
-Node.prototype._encode = function encode(data, path) {
+Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) {
+  return new EncoderBuffer(data, this.reporter);
+};
+
+Node.prototype._encode = function encode(data, reporter) {
   var state = this._baseState;
 
   // Decode root node
   if (state.parent === null)
-    return state.children[0]._encode(data, path || '');
+    return state.children[0]._encode(data, reporter || new Reporter());
 
   var result = null;
   var present = true;
 
+  // Set reporter to share it with a child class
+  this.reporter = reporter;
+
   // Check if data is there
   if (state.optional && data === undefined) {
     if (state['default'] !== null)
@@ -379,49 +389,54 @@ Node.prototype._encode = function encode(data, path) {
       return;
   }
 
+  // For error reporting
+  var prevKey;
+
   // Encode children first
   var content = null;
   var primitive = false;
   if (state.any) {
     // Anything that was given is translated to buffer
-    result = new EncoderBuffer(data);
+    result = this._createEncoderBuffer(data);
   } else if (state.children) {
     content = state.children.map(function(child) {
-      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) {
-        if (e instanceof EncoderError)
-          throw e;
-        else
-          throw new EncoderError(newpath, e);
-      }
+      if (child._baseState.key === null)
+        return reporter.error('Child should have a key');
+      var prevKey = reporter.enterKey(child._baseState.key);
+
+      if (typeof data !== 'object')
+        return reporter.error('Child expected, but input is not object');
+
+      var res = child._encode(data[child._baseState.key], reporter);
+      reporter.leaveKey(prevKey);
+
+      return res;
     }, this).filter(function(child) {
       return child;
     });
 
-    content = new EncoderBuffer(content);
+    content = this._createEncoderBuffer(content);
   } else {
     if (state.choice === null) {
       if (state.tag === 'seqof' || state.tag === 'setof') {
-        assert(state.args && state.args.length === 1);
-        assert(Array.isArray(data), 'seqof/setof, but data is not Array');
+        // TODO(indutny): this should be thrown on DSL level
+        if (!(state.args && state.args.length === 1))
+          return reporter.error('Too many args for : ' + state.tag);
 
-        content = new EncoderBuffer(data.map(function(item) {
-          return this._use(state.args[0], item, path);
+        if (!Array.isArray(data))
+          return reporter.error('seqof/setof, but data is not Array');
+
+        content = this._createEncoderBuffer(data.map(function(item) {
+          return this._use(state.args[0], item);
         }, this));
       } else if (state.use !== null) {
-        result = this._use(state.use, data, path);
+        result = this._use(state.use, data);
       } else {
         content = this._encodePrimitive(state.tag, data);
         primitive = true;
       }
     } else {
-      result = this._encodeChoice(data);
+      result = this._encodeChoice(data, reporter);
     }
   }
 
@@ -430,10 +445,12 @@ Node.prototype._encode = function encode(data, path) {
   if (!state.any && state.choice === null) {
     var tag = state.implicit !== null ? state.implicit : state.tag;
 
-    if (tag === null)
-      assert(state.use !== null, 'Tag could be ommited only for .use()');
-    else
+    if (tag === null) {
+      if (state.use === null)
+        reporter.error('Tag could be ommited only for .use()');
+    } else {
       result = this._encodeComposite(tag, primitive, content);
+    }
   }
 
   // Wrap in explicit
@@ -443,11 +460,11 @@ Node.prototype._encode = function encode(data, path) {
   return result;
 };
 
-Node.prototype._encodeChoice = function encodeChoice(data) {
+Node.prototype._encodeChoice = function encodeChoice(data, reporter) {
   var state = this._baseState;
 
   var node = state.choice[data.type];
-  return node._encode(data.value);
+  return node._encode(data.value, reporter);
 };
 
 Node.prototype._encodePrimitive = function encodePrimitive(tag, data) {
diff --git a/lib/asn1/base/reporter.js b/lib/asn1/base/reporter.js
new file mode 100644
index 0000000..746ccaa
--- /dev/null
+++ b/lib/asn1/base/reporter.js
@@ -0,0 +1,75 @@
+var util = require('util');
+
+var errRef = {};
+
+function Reporter(options) {
+  this._reporterState = {
+    obj: null,
+    path: [],
+    options: options || {},
+    errors: []
+  };
+}
+exports.Reporter = Reporter;
+
+Reporter.prototype.isError = function isError(obj) {
+  return obj === errRef;
+};
+
+Reporter.prototype.enterKey = function enterKey(key) {
+  return this._reporterState.path.push(key);
+};
+
+Reporter.prototype.leaveKey = function leaveKey(index, key, value) {
+  var state = this._reporterState;
+
+  state.path = state.path.slice(0, index - 1);
+  if (state.obj !== null)
+    state.obj[key] = value;
+};
+
+Reporter.prototype.enterObject = function enterObject() {
+  var state = this._reporterState;
+
+  var prev = state.obj;
+  state.obj = {};
+  return prev;
+};
+
+Reporter.prototype.leaveObject = function leaveObject(prev) {
+  var state = this._reporterState;
+
+  var now = state.obj;
+  state.obj = prev;
+  return now;
+};
+
+Reporter.prototype.error = function error(msg) {
+  var err;
+  var state = this._reporterState;
+
+  var inherited = msg instanceof ReporterError;
+  if (inherited) {
+    err = msg;
+  } else {
+    err = new ReporterError(state.path.map(function(elem) {
+      return '[' + JSON.stringify(elem) + ']';
+    }).join(''), msg.message || msg, msg.stack);
+  }
+
+  if (!state.options.partial)
+    throw err;
+
+  if (!inherited)
+    state.errors.push(err);
+
+  return errRef;
+};
+
+function ReporterError(path, msg, stack) {
+  var message = 'Error at object path: ' + path + '\n' + msg;
+  Error.call(this, message);
+
+  this.stack = stack || new Error(message).stack;
+};
+util.inherits(ReporterError, Error);
diff --git a/lib/asn1/decoders/der.js b/lib/asn1/decoders/der.js
index 385fb65..593eafe 100644
--- a/lib/asn1/decoders/der.js
+++ b/lib/asn1/decoders/der.js
@@ -1,4 +1,3 @@
-var assert = require('assert');
 var util = require('util');
 
 var asn1 = require('../../asn1');
@@ -18,11 +17,11 @@ function DERDecoder(entity) {
 };
 module.exports = DERDecoder;
 
-DERDecoder.prototype.decode = function decode(data) {
+DERDecoder.prototype.decode = function decode(data, options) {
   if (!(data instanceof base.DecoderBuffer))
-    data = new base.DecoderBuffer(data);
+    data = new base.DecoderBuffer(data, options);
 
-  return this.tree._decode(data);
+  return this.tree._decode(data, options);
 };
 
 // Tree methods
@@ -38,6 +37,9 @@ DERNode.prototype._peekTag = function peekTag(buffer, tag) {
 
   var state = buffer.save();
   var decodedTag = derDecodeTag(buffer);
+  if (buffer.isError(decodedTag))
+    return decodedTag;
+
   buffer.restore(state);
 
   return decodedTag.tag === tag || decodedTag.tagStr === tag;
@@ -45,13 +47,20 @@ DERNode.prototype._peekTag = function peekTag(buffer, tag) {
 
 DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) {
   var decodedTag = derDecodeTag(buffer);
+  if (buffer.isError(decodedTag))
+    return decodedTag;
+
   var len = derDecodeLen(buffer, decodedTag.primitive);
 
-  if (!any) {
-    assert(decodedTag.tag === tag ||
-           decodedTag.tagStr === tag ||
-           decodedTag.tagStr + 'of' === tag,
-           'Failed to match tag: ' + tag);
+  // Failure
+  if (buffer.isError(len))
+    return len;
+
+  if (!any &&
+      decodedTag.tag !== tag &&
+      decodedTag.tagStr !== tag &&
+      decodedTag.tagStr + 'of' !== tag) {
+    return buffer.error('Failed to match tag: ' + tag);
   }
 
   if (decodedTag.primitive || len !== null)
@@ -59,19 +68,31 @@ DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) {
 
   // Indefinite length... find END tag
   var state = buffer.save();
-  this._skipUntilEnd(buffer);
+  var res = this._skipUntilEnd(buffer);
+  if (buffer.isError(res))
+    return res;
+
   return buffer.restore(state);
 };
 
 DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer) {
   while (true) {
     var tag = derDecodeTag(buffer);
+    if (buffer.isError(tag))
+      return tag;
     var len = derDecodeLen(buffer, tag.primitive);
+    if (buffer.isError(len))
+      return len;
 
+    var res;
     if (tag.primitive || len !== null)
-      buffer.skip(len)
+      res = buffer.skip(len)
     else
-      this._skipUntilEnd(buffer);
+      res = this._skipUntilEnd(buffer);
+
+    // Failure
+    if (buffer.isError(res))
+      return res;
 
     if (tag.tagStr === 'end')
       break;
@@ -81,13 +102,14 @@ DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer) {
 DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder) {
   var result = [];
   while (!buffer.isEmpty()) {
-    try {
-      var possibleEnd = this._peekTag(buffer, 'end');
-      result.push(decoder.decode(buffer, 'der'));
-    } catch (e) {
-      if (possibleEnd)
-        break;
-    }
+    var possibleEnd = this._peekTag(buffer, 'end');
+    if (buffer.isError(possibleEnd))
+      return possibleEnd;
+
+    var res = decoder.decode(buffer, 'der');
+    if (buffer.isError(res) && possibleEnd)
+      break;
+    result.push(res);
   }
   return result;
 };
@@ -98,7 +120,7 @@ DERNode.prototype._decodeStr = function decodeStr(buffer, tag) {
   else if (tag === 'bitstr')
     return { unused: buffer.raw()[0], data: buffer.raw().slice(1) };
   else
-    assert(0, 'Decoding of string type: ' + tag + ' unsupported');
+    return this.error('Decoding of string type: ' + tag + ' unsupported');
 };
 
 DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) {
@@ -151,7 +173,7 @@ DERNode.prototype._decodeTime = function decodeTime(buffer, tag) {
     else
       year = 1900 + year;
   } else {
-    assert(0, 'Decoding ' + tag + ' time is not supported yet');
+    return this.error('Decoding ' + tag + ' time is not supported yet');
   }
 
   return Date.UTC(year, mon - 1, day, hour, min, sec, 0);
@@ -162,18 +184,25 @@ DERNode.prototype._decodeNull = function decodeNull(buffer) {
 };
 
 DERNode.prototype._decodeBool = function decodeBool(buffer) {
-  return buffer.readUInt8() !== 0;
+  var res = buffer.readUInt8();
+  if (buffer.isError(res))
+    return res;
+  else
+    return res !== 0;
 };
 
 DERNode.prototype._decodeInt = function decodeInt(buffer, values) {
   var res = 0;
   while (!buffer.isEmpty()) {
     res <<= 8;
-    res |= buffer.readUInt8();
+    var i = buffer.readUInt8();
+    if (buffer.isError(i))
+      return i;
+    res |= i;
   }
 
   if (values)
-    res = values[res];
+    res = values[res] || res;
   return res;
 };
 
@@ -185,6 +214,8 @@ DERNode.prototype._use = function use(buffer, decoder) {
 
 function derDecodeTag(buf) {
   var tag = buf.readUInt8();
+  if (buf.isError(tag))
+    return tag;
 
   var cls = der.tagClass[tag >> 6];
   var primitive = (tag & 0x20) === 0;
@@ -195,6 +226,9 @@ function derDecodeTag(buf) {
     tag = 0;
     while ((oct & 0x80) === 0x80) {
       oct = buf.readUInt8();
+      if (buf.isError(oct))
+        return oct;
+
       tag <<= 7;
       tag |= oct & 0x7f;
     }
@@ -213,6 +247,8 @@ function derDecodeTag(buf) {
 
 function derDecodeLen(buf, primitive) {
   var len = buf.readUInt8();
+  if (buf.isError(len))
+    return len;
 
   // Indefinite form
   if (!primitive && len === 0x80)
@@ -226,11 +262,16 @@ function derDecodeLen(buf, primitive) {
 
   // Long form
   var num = len & 0x7f;
-  assert(num < 4, 'length octect is too long');
+  if (num >= 4)
+    return buf.error('length octect is too long');
+
   len = 0;
   for (var i = 0; i < num; i++) {
     len <<= 8;
-    len |= buf.readUInt8();
+    var j = buf.readUInt8();
+    if (buf.isError(j))
+      return j;
+    len |= j;
   }
 
   return len;
diff --git a/lib/asn1/encoders/der.js b/lib/asn1/encoders/der.js
index 5d2d064..330838c 100644
--- a/lib/asn1/encoders/der.js
+++ b/lib/asn1/encoders/der.js
@@ -1,4 +1,3 @@
-var assert = require('assert');
 var util = require('util');
 var Buffer = require('buffer').Buffer;
 
@@ -19,8 +18,8 @@ function DEREncoder(entity) {
 };
 module.exports = DEREncoder;
 
-DEREncoder.prototype.encode = function encode(data, path) {
-  return this.tree._encode(data, path).join();
+DEREncoder.prototype.encode = function encode(data, reporter) {
+  return this.tree._encode(data, reporter).join();
 };
 
 // Tree methods
@@ -33,14 +32,14 @@ util.inherits(DERNode, base.Node);
 DERNode.prototype._encodeComposite = function encodeComposite(tag,
                                                               primitive,
                                                               content) {
-  var encodedTag = encodeTag(tag, primitive);
+  var encodedTag = encodeTag(tag, primitive, this.reporter);
 
   // Short form
   if (content.length < 0x80) {
     var header = new Buffer(2);
     header[0] = encodedTag;
     header[1] = content.length;
-    return new base.EncoderBuffer([ header, content ]);
+    return this._createEncoderBuffer([ header, content ]);
   }
 
   // Long form
@@ -56,32 +55,37 @@ DERNode.prototype._encodeComposite = function encodeComposite(tag,
   for (var i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8)
     header[i] = j & 0xff;
 
-  return new base.EncoderBuffer([ header, content ]);
+  return this._createEncoderBuffer([ header, content ]);
 };
 
 DERNode.prototype._encodeStr = function encodeStr(str, tag) {
   if (tag === 'octstr')
-    return new base.EncoderBuffer(str);
+    return this._createEncoderBuffer(str);
   else if (tag === 'bitstr')
-    return new base.EncoderBuffer([ str.unused | 0, str.data ]);
-  else
-    assert(0, 'Encoding of string type: ' + tag + ' unsupported');
+    return this._createEncoderBuffer([ str.unused | 0, str.data ]);
+  return this.reporter.error('Encoding of string type: ' + tag +
+                             ' unsupported');
 };
 
 DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) {
   if (typeof id === 'string') {
-    assert(values, 'string objid given, but no values map found');
-    assert(values.hasOwnProperty(id), 'objid not found in values map');
+    if (!values)
+      return this.reporter.error('string objid given, but no values map found');
+    if (!values.hasOwnProperty(id))
+      return this.reporter.error('objid not found in values map');
     id = values[id].split(/\s+/g);
     for (var i = 0; i < id.length; i++)
       id[i] |= 0;
   }
 
-  assert(Array.isArray(id),
-         'objid() should be either array or string, got: ' +
-              JSON.stringify(id));
+  if (!Array.isArray(id)) {
+    return this.reporter.error('objid() should be either array or string, ' +
+                               'got: ' + JSON.stringify(id));
+  }
+
   if (!relative) {
-    assert(id[1] < 40, 'Second objid identifier OOB');
+    if (id[1] >= 40)
+      return this.reporter.error('Second objid identifier OOB');
     id.splice(0, 2, id[0] * 40 + id[1]);
   }
 
@@ -102,7 +106,7 @@ DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) {
       objid[offset--] = 0x80 | (ident & 0x7f);
   }
 
-  return new base.EncoderBuffer(objid);
+  return this._createEncoderBuffer(objid);
 };
 
 function two(num) {
@@ -137,26 +141,29 @@ DERNode.prototype._encodeTime = function encodeTime(time, tag) {
       'Z'
     ].join('');
   } else {
-    assert(0, 'Encoding ' + tag + ' time is not supported yet');
+    this.reporter.error('Encoding ' + tag + ' time is not supported yet');
   }
 
   return this._encodeStr(str, 'octstr');
 };
 
 DERNode.prototype._encodeNull = function encodeNull() {
-  return new base.EncoderBuffer('');
+  return this._createEncoderBuffer('');
 };
 
 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: ' + JSON.stringify(num));
+    if (!values)
+      return this.reporter.error('String int or enum given, but no values map');
+    if (!values.hasOwnProperty(num)) {
+      return this.reporter.error('Values map doesn\'t contain: ' +
+                                 JSON.stringify(num));
+    }
     num = values[num];
   }
 
   if (num < 0x100)
-    return new base.EncoderBuffer(num);
+    return this._createEncoderBuffer(num);
 
   var size = 1;
   for (var i = num; i >= 0x100; i >>= 8)
@@ -168,20 +175,20 @@ DERNode.prototype._encodeInt = function encodeInt(num, values) {
     num >>= 8;
   }
 
-  return new base.EncoderBuffer(out);
+  return this._createEncoderBuffer(out);
 };
 
 DERNode.prototype._encodeBool = function encodeBool(value) {
-  return new base.EncoderBuffer(value ? 0xff : 0);
+  return this._createEncoderBuffer(value ? 0xff : 0);
 };
 
-DERNode.prototype._use = function use(encoder, data, path) {
-  return encoder.encode(data, 'der', path);
+DERNode.prototype._use = function use(encoder, data) {
+  return encoder.encode(data, 'der', this.reporter);
 };
 
 // Utility methods
 
-function encodeTag(tag, primitive, cls) {
+function encodeTag(tag, primitive, cls, reporter) {
   var res;
 
   if (tag === 'seqof')
@@ -194,9 +201,10 @@ function encodeTag(tag, primitive, cls) {
   else if (typeof tag === 'number' && (tag | 0) === tag)
     res = tag;
   else
-    throw new Error('Unknown tag: ' + tag);
+    return reporter.error('Unknown tag: ' + tag);
 
-  assert(res < 0x1f, 'Multi-octet tag encoding unsupported');
+  if (res >= 0x1f)
+    return reporter.error('Multi-octet tag encoding unsupported');
 
   if (!primitive)
     res |= 0x20;
diff --git a/test/encode-error-test.js b/test/encode-error-test.js
index 113805d..7d1c5f8 100644
--- a/test/encode-error-test.js
+++ b/test/encode-error-test.js
@@ -43,7 +43,7 @@ describe('asn1.js encode error', function() {
       this.seq().obj(
         this.key('key').int()
       );
-    }, { key: 'hello' } , /object path: "key"/i);
+    }, { key: 'hello' } , /object path: \["key"\]/i);
 
     test('deep and empty', function() {
       this.seq().obj(
@@ -53,7 +53,7 @@ describe('asn1.js encode error', function() {
           )
         )
       );
-    }, { } , /object path: "a.b"/i);
+    }, { } , /object path: \["a"\]\["b"\]/i);
 
     test('deep', function() {
       this.seq().obj(
@@ -63,7 +63,7 @@ describe('asn1.js encode error', function() {
           )
         )
       );
-    }, { a: { b: { c: 'hello' } } } , /object path: "a.b.c"/i);
+    }, { a: { b: { c: 'hello' } } } , /object path: \["a"\]\["b"\]\["c"\]/i);
 
     test('use', function() {
       var S = asn1.define('S', function() {
@@ -77,6 +77,6 @@ describe('asn1.js encode error', function() {
           this.key('b').use(S)
         )
       );
-    }, { a: { b: { x: 'hello' } } } , /object path: "a.b.x"/i);
+    }, { 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