diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index c832f747..cd47d62d 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -1225,7 +1225,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) { // Note that minimaldata is not checked // on unexecuted branches of code. if (negate === 0) { - if (!Script.checkMinimal(op.data, op.value, flags)) + if (!Script.isMinimal(op.data, op.value, flags)) throw new ScriptError('MINIMALDATA', op, ip); stack.push(op.data); } @@ -2170,7 +2170,7 @@ Script.prototype.removeData = function removeData(data) { if (!op.data) continue; - if (!Script.checkMinimal(op.data, op.value)) + if (!Script.isMinimal(op.data, op.value)) continue; if (utils.equal(op.data, data)) @@ -2222,7 +2222,7 @@ Script.prototype.indexOf = function indexOf(data) { * @returns {Boolean} */ -Script.checkMinimal = function checkMinimal(data, opcode, flags) { +Script.isMinimal = function isMinimal(data, opcode, flags) { if (flags == null) flags = constants.flags.STANDARD_VERIFY_FLAGS; @@ -3030,20 +3030,50 @@ Script.prototype.getCoinbaseHeight = function getCoinbaseHeight() { */ Script.getCoinbaseHeight = function getCoinbaseHeight(raw) { - var height; + var flags = constants.flags.STANDARD_VERIFY_FLAGS; + var data, height, op; if (raw.length === 0) return -1; + // Small ints are allowed. height = Script.getSmall(raw[0]); if (height !== -1) return height; - if (raw[0] <= 0x06 && raw.length >= 1 + raw[0]) + // No more than 6 bytes (we can't + // handle 7 byte JS numbers and + // height 281 trillion is far away). + if (raw[0] > 0x06) return -1; - return new bn(raw.slice(1, 1 + raw[0]), 'le').toNumber(); + // No bad pushes allowed. + if (raw.length < 1 + raw[0]) + return -1; + + data = raw.slice(1, 1 + raw[0]); + + // Deserialize the height. + try { + height = Script.num(data, flags, 6); + } catch (e) { + return -1; + } + + // Reserialize the height. + op = Opcode.fromNumber(height); + + // Should have been OP_0-OP_16. + if (!op.data) + return -1; + + // Ensure the miner serialized the + // number in the most minimal fashion. + if (!utils.equal(data, op.data)) + return -1; + + return height.toNumber(); }; /**