Browse Source

fixed segfault in bignum.h, additional security limits, refactoring

-- version 0.3.7
0.8 v0.3.7
Satoshi Nakamoto 15 years ago committed by Gavin Andresen
parent
commit
73aa262647
  1. 18
      bignum.h
  2. 3
      main.cpp
  3. 32
      script.cpp
  4. 2
      script.h
  5. 2
      serialize.h
  6. 6
      setup.nsi

18
bignum.h

@ -401,8 +401,16 @@ public:
CBigNum& operator>>=(unsigned int shift) CBigNum& operator>>=(unsigned int shift)
{ {
// Note: BN_rshift segfaults on 64-bit ubuntu 9.10 if 2^shift is greater than the number, // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
// tested OK on 64-bit ubuntu 10.4 // if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
CBigNum a = 1;
a <<= shift;
if (BN_cmp(&a, this) > 0)
{
*this = 0;
return *this;
}
if (!BN_rshift(this, this, shift)) if (!BN_rshift(this, this, shift))
throw bignum_error("CBigNum:operator>>= : BN_rshift failed"); throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
return *this; return *this;
@ -511,10 +519,8 @@ inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
inline const CBigNum operator>>(const CBigNum& a, unsigned int shift) inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
{ {
CBigNum r; CBigNum r = a;
// Note: BN_rshift segfaults on 64-bit ubuntu 9.10 if 2^shift is greater than the number r >>= shift;
if (!BN_rshift(&r, &a, shift))
throw bignum_error("CBigNum:operator>> : BN_rshift failed");
return r; return r;
} }

3
main.cpp

@ -3036,7 +3036,8 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
foreach(CWalletTx* pcoin, setCoins) foreach(CWalletTx* pcoin, setCoins)
for (int nOut = 0; nOut < pcoin->vout.size(); nOut++) for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)
if (pcoin->vout[nOut].IsMine()) if (pcoin->vout[nOut].IsMine())
SignSignature(*pcoin, wtxNew, nIn++); if (!SignSignature(*pcoin, wtxNew, nIn++))
return false;
// Check that enough fee is included // Check that enough fee is included
if (nFee < wtxNew.GetMinFee()) if (nFee < wtxNew.GetMinFee())

32
script.cpp

@ -42,20 +42,17 @@ void MakeSameSize(valtype& vch1, valtype& vch2)
#define stacktop(i) (stack.at(stack.size()+(i))) #define stacktop(i) (stack.at(stack.size()+(i)))
#define altstacktop(i) (altstack.at(altstack.size()+(i))) #define altstacktop(i) (altstack.at(altstack.size()+(i)))
bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType, bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType)
vector<vector<unsigned char> >* pvStackRet)
{ {
CAutoBN_CTX pctx; CAutoBN_CTX pctx;
CScript::const_iterator pc = script.begin(); CScript::const_iterator pc = script.begin();
CScript::const_iterator pend = script.end(); CScript::const_iterator pend = script.end();
CScript::const_iterator pbegincodehash = script.begin(); CScript::const_iterator pbegincodehash = script.begin();
vector<bool> vfExec; vector<bool> vfExec;
vector<valtype> stack;
vector<valtype> altstack; vector<valtype> altstack;
if (pvStackRet) if (script.size() > 10000)
pvStackRet->clear();
if (script.size() > 20000)
return false; return false;
int nOpCount = 0;
try try
@ -73,6 +70,8 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
return false; return false;
if (vchPushValue.size() > 5000) if (vchPushValue.size() > 5000)
return false; return false;
if (opcode > OP_16 && nOpCount++ > 200)
return false;
if (fExec && opcode <= OP_PUSHDATA4) if (fExec && opcode <= OP_PUSHDATA4)
stack.push_back(vchPushValue); stack.push_back(vchPushValue);
@ -828,9 +827,7 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
if (!vfExec.empty()) if (!vfExec.empty())
return false; return false;
if (pvStackRet) return true;
*pvStackRet = stack;
return (stack.empty() ? false : CastToBool(stack.back()));
} }
#undef top #undef top
@ -1114,6 +1111,19 @@ bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret)
} }
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
vector<vector<unsigned char> > stack;
if (!EvalScript(stack, scriptSig, txTo, nIn, nHashType))
return false;
if (!EvalScript(stack, scriptPubKey, txTo, nIn, nHashType))
return false;
if (stack.empty())
return false;
return CastToBool(stack.back());
}
bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq) bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
{ {
assert(nIn < txTo.vin.size()); assert(nIn < txTo.vin.size());
@ -1132,7 +1142,7 @@ bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int
// Test solution // Test solution
if (scriptPrereq.empty()) if (scriptPrereq.empty())
if (!EvalScript(txin.scriptSig + CScript(OP_CODESEPARATOR) + txout.scriptPubKey, txTo, nIn)) if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, 0))
return false; return false;
return true; return true;
@ -1150,7 +1160,7 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig
if (txin.prevout.hash != txFrom.GetHash()) if (txin.prevout.hash != txFrom.GetHash())
return false; return false;
if (!EvalScript(txin.scriptSig + CScript(OP_CODESEPARATOR) + txout.scriptPubKey, txTo, nIn, nHashType)) if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType))
return false; return false;
// Anytime a signature is successfully verified, it's proof the outpoint is spent, // Anytime a signature is successfully verified, it's proof the outpoint is spent,

2
script.h

@ -657,8 +657,6 @@ public:
bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType=0,
vector<vector<unsigned char> >* pvStackRet=NULL);
uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
bool IsMine(const CScript& scriptPubKey); bool IsMine(const CScript& scriptPubKey);
bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet); bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet);

2
serialize.h

@ -19,7 +19,7 @@ class CScript;
class CDataStream; class CDataStream;
class CAutoFile; class CAutoFile;
static const int VERSION = 306; static const int VERSION = 307;
static const char* pszSubVer = ""; static const char* pszSubVer = "";

6
setup.nsi

@ -7,7 +7,7 @@ RequestExecutionLevel highest
# General Symbol Definitions # General Symbol Definitions
!define REGKEY "SOFTWARE\$(^Name)" !define REGKEY "SOFTWARE\$(^Name)"
!define VERSION 0.3.6 !define VERSION 0.3.7
!define COMPANY "Bitcoin project" !define COMPANY "Bitcoin project"
!define URL http://www.bitcoin.org/ !define URL http://www.bitcoin.org/
@ -42,12 +42,12 @@ Var StartMenuGroup
!insertmacro MUI_LANGUAGE English !insertmacro MUI_LANGUAGE English
# Installer attributes # Installer attributes
OutFile bitcoin-0.3.6-win32-setup.exe OutFile bitcoin-0.3.7-win32-setup.exe
InstallDir $PROGRAMFILES\Bitcoin InstallDir $PROGRAMFILES\Bitcoin
CRCCheck on CRCCheck on
XPStyle on XPStyle on
ShowInstDetails show ShowInstDetails show
VIProductVersion 0.3.6.0 VIProductVersion 0.3.7.0
VIAddVersionKey ProductName Bitcoin VIAddVersionKey ProductName Bitcoin
VIAddVersionKey ProductVersion "${VERSION}" VIAddVersionKey ProductVersion "${VERSION}"
VIAddVersionKey CompanyName "${COMPANY}" VIAddVersionKey CompanyName "${COMPANY}"

Loading…
Cancel
Save