Mercurial > hg > bitcoin
changeset 3553:6405b2b19c99 draft
Documented bug in sign-extension behavior of opcodes OP_AND, OP_OR, and OP_XOR.
Due to a bug in the implementation of MakeSameSize(), using OP_AND, OP_OR, or OP_XOR with signed values of unequal size will result in the sign-value becoming part of the smaller integer, with nonsensical results. This patch documents the unexpected behavior and provides the basis of a solution should decision be made to fix the bug in the future.
author | Mark Friedenbach <mark@monetize.io> |
---|---|
date | Tue, 25 Sep 2012 16:40:34 -0700 (2012-09-25) |
parents | 195390ef8c91 |
children | 05d1e819a8ee |
files | src/script.cpp |
diffstat | 1 files changed, 23 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/script.cpp +++ b/src/script.cpp @@ -54,12 +54,29 @@ return false; } +// +// WARNING: This does not work as expected for signed integers; the sign-bit +// is left in place as the integer is zero-extended. The correct behavior +// would be to move the most significant bit of the last byte during the +// resize process. MakeSameSize() is currently only used by the disabled +// opcodes OP_AND, OP_OR, and OP_XOR. +// void MakeSameSize(valtype& vch1, valtype& vch2) { // Lengthen the shorter one if (vch1.size() < vch2.size()) + // PATCH: + // +unsigned char msb = vch1[vch1.size()-1]; + // +vch1[vch1.size()-1] &= 0x7f; + // vch1.resize(vch2.size(), 0); + // +vch1[vch1.size()-1] = msb; vch1.resize(vch2.size(), 0); if (vch2.size() < vch1.size()) + // PATCH: + // +unsigned char msb = vch2[vch2.size()-1]; + // +vch2[vch2.size()-1] &= 0x7f; + // vch2.resize(vch1.size(), 0); + // +vch2[vch2.size()-1] = msb; vch2.resize(vch1.size(), 0); } @@ -663,6 +680,11 @@ } break; + // + // WARNING: These disabled opcodes exhibit unexpected behavior + // when used on signed integers due to a bug in MakeSameSize() + // [see definition of MakeSameSize() above]. + // case OP_AND: case OP_OR: case OP_XOR: @@ -672,7 +694,7 @@ return false; valtype& vch1 = stacktop(-2); valtype& vch2 = stacktop(-1); - MakeSameSize(vch1, vch2); + MakeSameSize(vch1, vch2); // <-- NOT SAFE FOR SIGNED VALUES if (opcode == OP_AND) { for (unsigned int i = 0; i < vch1.size(); i++)