Skip to content

Commit cce158e

Browse files
committed
msgpack.pack Support Cyclic Reference Error
Signed-off-by: uupaa <[email protected]>
1 parent b6abeea commit cce158e

File tree

2 files changed

+46
-16
lines changed

2 files changed

+46
-16
lines changed

msgpack.js

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
/*!{id:msgpack.js,ver:1.03,license:"MIT",author:"uupaa.js@gmail.com"}*/
1+
/*!{id:msgpack.js,ver:1.04,license:"MIT",author:"uupaa.js@gmail.com"}*/
22

33
// === msgpack ===
44
// MessagePack -> http://msgpack.sourceforge.net/
55

66
this.msgpack || (function(globalScope) {
77

88
globalScope.msgpack = {
9-
pack: msgpackpack, // msgpack.pack(data:Mix, toString:Boolean = false):ByteArray/ByteString
9+
pack: msgpackpack, // msgpack.pack(data:Mix, toString:Boolean = false):ByteArray/ByteString/false
1010
// [1][mix to String] msgpack.pack({}, true) -> "..."
1111
// [2][mix to ByteArray] msgpack.pack({}) -> [...]
1212
unpack: msgpackunpack, // msgpack.unpack(data:BinaryString/ByteArray):Mix
@@ -25,8 +25,10 @@ var _ie = /MSIE/.test(navigator.userAgent),
2525
_sign = { 8: 0x80, 16: 0x8000, 32: 0x80000000 },
2626
_buf = [], // decode buffer
2727
_idx = 0, // decode buffer[index]
28+
_error = 0, // msgpack.pack() error code. 1 = CYCLIC_REFERENCE_ERROR
2829
_ary = [], // pooled array
29-
_toString = Object.prototype.toString;
30+
_toString = Object.prototype.toString,
31+
_MAX_DEPTH = 512;
3032

3133
// for WebWorkers Code Block
3234
self.importScripts && (onmessage = function(event) {
@@ -40,14 +42,18 @@ self.importScripts && (onmessage = function(event) {
4042
// msgpack.pack
4143
function msgpackpack(data, // @param Mix:
4244
toString) { // @param Boolean(= false):
43-
// @return ByteArray/BinaryString:
45+
// @return ByteArray/BinaryString/false:
46+
// false is Error
4447
// [1][mix to String] msgpack.pack({}, true) -> "..."
4548
// [2][mix to ByteArray] msgpack.pack({}) -> [...]
4649

47-
var byteArray = encode([], data);
50+
_error = 0;
4851

49-
return toString ? byteArrayToByteString(byteArray)
50-
: byteArray;
52+
var byteArray = encode([], data, 0);
53+
54+
return _error ? false
55+
: toString ? byteArrayToByteString(byteArray)
56+
: byteArray;
5157
}
5258

5359
// msgpack.unpack
@@ -62,10 +68,11 @@ function msgpackunpack(data) { // @param BinaryString/ByteArray:
6268
}
6369

6470
// inner - encoder
65-
function encode(rv, // @param ByteArray: result
66-
mix) { // @param Mix: source data
67-
var size = 0, i = 0, iz, c, pos,
68-
high, low, i64 = 0, sign, exp, frac;
71+
function encode(rv, // @param ByteArray: result
72+
mix, // @param Mix: source data
73+
depth) { // @param Number: depth
74+
var size = 0, i = 0, iz = 0, c = 0, pos = 0,
75+
high = 0, low = 0, i64 = 0, sign = false, exp = 0, frac = 0;
6976

7077
if (mix == null) { // null or undefined
7178
rv.push(0xc0);
@@ -148,7 +155,7 @@ function encode(rv, // @param ByteArray: result
148155
// 1 4 09 6
149156
low = frac & 0xffffffff;
150157
high = ((frac / 0x100000000) & 0xfffff) | (exp << 20);
151-
sign && (high += 0x80000000);
158+
sign && (high |= 0x80000000);
152159

153160
rv.push(0xcb, (high >> 24) & 0xff, (high >> 16) & 0xff,
154161
(high >> 8) & 0xff, high & 0xff,
@@ -192,11 +199,15 @@ function encode(rv, // @param ByteArray: result
192199
}
193200
break;
194201
default: // array or hash
202+
if (depth >= _MAX_DEPTH) {
203+
_error = 1; // CYCLIC_REFERENCE_ERROR
204+
return rv = [];
205+
}
195206
if (_toString.call(mix) === "[object Array]") { // array
196207
size = mix.length;
197208
setType(rv, 16, size, [0x90, 0xdc, 0xdd]);
198209
for (; i < size; ++i) {
199-
encode(rv, mix[i]);
210+
encode(rv, mix[i], depth + 1);
200211
}
201212
} else { // hash
202213
// http://d.hatena.ne.jp/uupaa/20101129
@@ -208,8 +219,8 @@ function encode(rv, // @param ByteArray: result
208219

209220
for (i in mix) {
210221
++size;
211-
encode(rv, i);
212-
encode(rv, mix[i]);
222+
encode(rv, i, depth + 1);
223+
encode(rv, mix[i], depth + 1);
213224
}
214225

215226
// rewrite hash type.
@@ -229,7 +240,8 @@ function encode(rv, // @param ByteArray: result
229240

230241
// inner - decoder
231242
function decode() { // @return Mix:
232-
var ary, hash, num = 0, i = 0, iz, msb = 0, c, sign, exp, frac, key,
243+
var ary, hash, num = 0, i = 0, iz = 0, msb = 0, c = 0, sign = 0,
244+
exp = 0, frac = 0, key,
233245
buf = _buf, type = buf[++_idx];
234246

235247
if (type >= 0xe0) { // Negative FixNum (111x xxxx) (-32 ~ -1)

test/codec.htm

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,24 @@
12341234
var rv = msgpack.unpack(pack);
12351235

12361236
return [rv, "is", data, hex(pack)];
1237+
},
1238+
"Cyclic Reference Error": "",
1239+
"Hash": function() {
1240+
var ary = [];
1241+
var hash = {
1242+
ary: ary
1243+
};
1244+
ary[0] = hash;
1245+
1246+
var pack = msgpack.pack(hash);
1247+
var rv;
1248+
1249+
if (pack === false) {
1250+
return [rv, "is false"];
1251+
} else {
1252+
rv = msgpack.unpack(pack);
1253+
return [rv, "==", 0, hex(pack)];
1254+
}
12371255
}
12381256
});
12391257
});

0 commit comments

Comments
 (0)