protobuf.js使用uint64类型超过16位长度decode的bug
原版在这里:
https://www.npmjs.com/package/protobufjs
protobuf-library.js里有个LongBits的原型toNumber是这样写的:
LongBits.prototype.toNumber = function toNumber(unsigned) {
if (!unsigned && this.hi >>> 31) {
var lo = ~this.lo + 1 >>> 0,
hi = ~this.hi >>> 0;
if (!lo)
hi = hi + 1 >>> 0;
return -(lo + hi * 4294967296);
}
return this.lo + this.hi * 4294967296;
};
我一步步查到
this.lo + this.hi * 4294967296;
的时候发现精度有问题
搜了好久发现了一个BigInt解决这个问题
修改后如下:
LongBits.prototype.toNumber = function toNumber(unsigned) {
if (!unsigned && this.hi >>> 31) {
var lo = ~this.lo + 1 >>> 0,
hi = ~this.hi >>> 0;
if (!lo)
hi = hi + 1 >>> 0;
return -(lo + hi * 4294967296);
}
return (BigInt(this.lo) + BigInt(this.hi * 4294967296)).toString();
};
proto_bundle.min文件搜索
this.lo+4294967296*this.hi
进行替换
(BigInt(this.lo)+BigInt(4294967296*this.hi)).toString()
protobuf-library.min文件搜
this.lo+this.hi*4294967296
进行替换
(BigInt(this.lo)+BigInt(this.hi*4294967296)).toString()
解决方案2:
protobuf-library.js开头引用
let bigIntXXX;
if(!window.bigInt) {
bigIntXXX = require("./BigInteger.js");
}
else {
bigIntXXX = bigInt;
}
LongBits.prototype.toNumber修改为
LongBits.prototype.toNumber = function toNumber(unsigned) {
if (!unsigned && this.hi >>> 31) {
var lo = ~this.lo + 1 >>> 0,
hi = ~this.hi >>> 0;
if (!lo)
hi = hi + 1 >>> 0;
return -(lo + hi * 4294967296);
}
let xxx = bigIntXXX(this.lo.toString()).add(bigIntXXX(this.hi.toString()).multiply(4294967296));
return xxx.toString();
};