From 73aa262647ff9948eaf95e83236ec323347e95d0 Mon Sep 17 00:00:00 2001 From: Satoshi Nakamoto Date: Sat, 31 Jul 2010 20:12:05 +0000 Subject: fixed segfault in bignum.h, additional security limits, refactoring -- version 0.3.7 --- bignum.h | 18 ++++++++++++------ main.cpp | 3 ++- script.cpp | 32 +++++++++++++++++++++----------- script.h | 2 -- serialize.h | 2 +- setup.nsi | 6 +++--- 6 files changed, 39 insertions(+), 24 deletions(-) diff --git a/bignum.h b/bignum.h index 2dd6593b5a..450e809d3d 100644 --- a/bignum.h +++ b/bignum.h @@ -401,8 +401,16 @@ public: CBigNum& operator>>=(unsigned int shift) { - // Note: BN_rshift segfaults on 64-bit ubuntu 9.10 if 2^shift is greater than the number, - // tested OK on 64-bit ubuntu 10.4 + // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number + // 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)) throw bignum_error("CBigNum:operator>>= : BN_rshift failed"); 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) { - CBigNum r; - // Note: BN_rshift segfaults on 64-bit ubuntu 9.10 if 2^shift is greater than the number - if (!BN_rshift(&r, &a, shift)) - throw bignum_error("CBigNum:operator>> : BN_rshift failed"); + CBigNum r = a; + r >>= shift; return r; } diff --git a/main.cpp b/main.cpp index da2a6ac903..c8d91514e9 100644 --- a/main.cpp +++ b/main.cpp @@ -3036,7 +3036,8 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK foreach(CWalletTx* pcoin, setCoins) for (int nOut = 0; nOut < pcoin->vout.size(); nOut++) if (pcoin->vout[nOut].IsMine()) - SignSignature(*pcoin, wtxNew, nIn++); + if (!SignSignature(*pcoin, wtxNew, nIn++)) + return false; // Check that enough fee is included if (nFee < wtxNew.GetMinFee()) diff --git a/script.cpp b/script.cpp index 823dc56d01..96d9c371a6 100644 --- a/script.cpp +++ b/script.cpp @@ -42,20 +42,17 @@ void MakeSameSize(valtype& vch1, valtype& vch2) #define stacktop(i) (stack.at(stack.size()+(i))) #define altstacktop(i) (altstack.at(altstack.size()+(i))) -bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType, - vector >* pvStackRet) +bool EvalScript(vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType) { CAutoBN_CTX pctx; CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); CScript::const_iterator pbegincodehash = script.begin(); vector vfExec; - vector stack; vector altstack; - if (pvStackRet) - pvStackRet->clear(); - if (script.size() > 20000) + if (script.size() > 10000) return false; + int nOpCount = 0; try @@ -73,6 +70,8 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI return false; if (vchPushValue.size() > 5000) return false; + if (opcode > OP_16 && nOpCount++ > 200) + return false; if (fExec && opcode <= OP_PUSHDATA4) stack.push_back(vchPushValue); @@ -828,9 +827,7 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI if (!vfExec.empty()) return false; - if (pvStackRet) - *pvStackRet = stack; - return (stack.empty() ? false : CastToBool(stack.back())); + return true; } #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 > 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) { assert(nIn < txTo.vin.size()); @@ -1132,7 +1142,7 @@ bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int // Test solution 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 true; @@ -1150,7 +1160,7 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig if (txin.prevout.hash != txFrom.GetHash()) 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; // Anytime a signature is successfully verified, it's proof the outpoint is spent, diff --git a/script.h b/script.h index 4efc002aaf..20d29312bd 100644 --- a/script.h +++ b/script.h @@ -657,8 +657,6 @@ public: -bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType=0, - vector >* pvStackRet=NULL); uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); bool IsMine(const CScript& scriptPubKey); bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector& vchPubKeyRet); diff --git a/serialize.h b/serialize.h index 8336136ed0..ba6e8df87e 100644 --- a/serialize.h +++ b/serialize.h @@ -19,7 +19,7 @@ class CScript; class CDataStream; class CAutoFile; -static const int VERSION = 306; +static const int VERSION = 307; static const char* pszSubVer = ""; diff --git a/setup.nsi b/setup.nsi index 92a07b717e..72c961b060 100644 --- a/setup.nsi +++ b/setup.nsi @@ -7,7 +7,7 @@ RequestExecutionLevel highest # General Symbol Definitions !define REGKEY "SOFTWARE\$(^Name)" -!define VERSION 0.3.6 +!define VERSION 0.3.7 !define COMPANY "Bitcoin project" !define URL http://www.bitcoin.org/ @@ -42,12 +42,12 @@ Var StartMenuGroup !insertmacro MUI_LANGUAGE English # Installer attributes -OutFile bitcoin-0.3.6-win32-setup.exe +OutFile bitcoin-0.3.7-win32-setup.exe InstallDir $PROGRAMFILES\Bitcoin CRCCheck on XPStyle on ShowInstDetails show -VIProductVersion 0.3.6.0 +VIProductVersion 0.3.7.0 VIAddVersionKey ProductName Bitcoin VIAddVersionKey ProductVersion "${VERSION}" VIAddVersionKey CompanyName "${COMPANY}" -- cgit v1.2.3