changeset 192:2f1d353a4b54 draft

fixed segfault in bignum.h, additional security limits, refactoring -- version 0.3.7
author Satoshi Nakamoto <satoshin@gmx.com>
date Sat, 31 Jul 2010 20:12:05 +0000
parents adba43a24a05
children 83513e9c3f0c
files bignum.h main.cpp script.cpp script.h serialize.h setup.nsi
diffstat 6 files changed, 39 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/bignum.h
+++ b/bignum.h
@@ -401,8 +401,16 @@
 
     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)
 {
-    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;
 }
 
--- a/main.cpp
+++ b/main.cpp
@@ -3036,7 +3036,8 @@
                 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())
--- a/script.cpp
+++ b/script.cpp
@@ -42,20 +42,17 @@
 #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<vector<unsigned char> >* pvStackRet)
+bool EvalScript(vector<vector<unsigned char> >& 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<bool> vfExec;
-    vector<valtype> stack;
     vector<valtype> altstack;
-    if (pvStackRet)
-        pvStackRet->clear();
-    if (script.size() > 20000)
+    if (script.size() > 10000)
         return false;
+    int nOpCount = 0;
 
 
     try
@@ -73,6 +70,8 @@
                 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 @@
     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 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)
 {
     assert(nIn < txTo.vin.size());
@@ -1132,7 +1142,7 @@
 
     // 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 @@
     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,
--- a/script.h
+++ b/script.h
@@ -657,8 +657,6 @@
 
 
 
-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);
 bool IsMine(const CScript& scriptPubKey);
 bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet);
--- a/serialize.h
+++ b/serialize.h
@@ -19,7 +19,7 @@
 class CDataStream;
 class CAutoFile;
 
-static const int VERSION = 306;
+static const int VERSION = 307;
 static const char* pszSubVer = "";
 
 
--- a/setup.nsi
+++ b/setup.nsi
@@ -7,7 +7,7 @@
 
 # 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 @@
 !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}"