fix(nspv): add missing length lower-bounds before request/vopret reads

nSPV handlers (gated behind non-default -nspv_msg) read request[1]/vopret[1]
before confirming the peer sent >=2 bytes:

#6 (MEDIUM) NSPV_UTXOS/NSPV_TXIDS evaluated request[1] whenever len<69 (incl
len==1); the 4351d5b73 value-clamp left this lower bound open. The TXIDS/MEMPOOL
else-branch debug prints also read request[1] unconditionally. Add len>=2 guards
/ drop request[1] from the prints.

#7 (LOW) NSPV_MEMPOOL_CCEVALCODE read vopret[1] on a possibly-1-byte vector.
Guard with vopret.size()>=2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 11:21:28 -05:00
parent 7e9b2c6615
commit 11704e6023

View File

@@ -324,7 +324,7 @@ int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector<uint25
CScript scriptPubKey = tx.vout[tx.vout.size()-1].scriptPubKey; CScript scriptPubKey = tx.vout[tx.vout.size()-1].scriptPubKey;
if ( GetOpReturnData(scriptPubKey,vopret) != 0 ) if ( GetOpReturnData(scriptPubKey,vopret) != 0 )
{ {
if ( vopret[0] == evalcode && vopret[1] == func ) if ( vopret.size() >= 2 && vopret[0] == evalcode && vopret[1] == func )
{ {
txids.push_back(hash); txids.push_back(hash);
num++; num++;
@@ -657,7 +657,7 @@ void hush_nSPVreq(CNode *pfrom,std::vector<uint8_t> request) // received a reque
if ( timestamp > pfrom->prevtimes[ind] ) if ( timestamp > pfrom->prevtimes[ind] )
{ {
struct NSPV_utxosresp U; struct NSPV_utxosresp U;
if ( len < 64+5 && request[1] < 64 && (request[1] == len-3 || request[1] == len-7 || request[1] == len-11) ) if ( len >= 2 && len < 64+5 && request[1] < 64 && (request[1] == len-3 || request[1] == len-7 || request[1] == len-11) )
{ {
int32_t skipcount = 0; char coinaddr[64]; uint8_t filter; uint8_t isCC = 0; int32_t skipcount = 0; char coinaddr[64]; uint8_t filter; uint8_t isCC = 0;
memcpy(coinaddr,&request[2],request[1]); // request[1] < 64 bounds the copy + the terminator write memcpy(coinaddr,&request[2],request[1]); // request[1] < 64 bounds the copy + the terminator write
@@ -697,7 +697,7 @@ void hush_nSPVreq(CNode *pfrom,std::vector<uint8_t> request) // received a reque
if ( timestamp > pfrom->prevtimes[ind] ) if ( timestamp > pfrom->prevtimes[ind] )
{ {
struct NSPV_txidsresp T; struct NSPV_txidsresp T;
if ( len < 64+5 && request[1] < 64 && (request[1] == len-3 || request[1] == len-7 || request[1] == len-11) ) if ( len >= 2 && len < 64+5 && request[1] < 64 && (request[1] == len-3 || request[1] == len-7 || request[1] == len-11) )
{ {
int32_t skipcount = 0; char coinaddr[64]; uint32_t filter; uint8_t isCC = 0; int32_t skipcount = 0; char coinaddr[64]; uint32_t filter; uint8_t isCC = 0;
memcpy(coinaddr,&request[2],request[1]); // request[1] < 64 bounds the copy + the terminator write memcpy(coinaddr,&request[2],request[1]); // request[1] < 64 bounds the copy + the terminator write
@@ -730,7 +730,7 @@ void hush_nSPVreq(CNode *pfrom,std::vector<uint8_t> request) // received a reque
} }
NSPV_txidsresp_purge(&T); NSPV_txidsresp_purge(&T);
} }
} else fprintf(stderr,"len.%d req1.%d\n",len,request[1]); } else fprintf(stderr,"len.%d\n",len);
} }
} }
else if ( request[0] == NSPV_MEMPOOL ) else if ( request[0] == NSPV_MEMPOOL )
@@ -767,7 +767,7 @@ void hush_nSPVreq(CNode *pfrom,std::vector<uint8_t> request) // received a reque
NSPV_mempoolresp_purge(&M); NSPV_mempoolresp_purge(&M);
} }
} }
} else fprintf(stderr,"len.%d req1.%d\n",len,request[1]); } else fprintf(stderr,"len.%d\n",len);
} }
} }
else if ( request[0] == NSPV_NTZS ) else if ( request[0] == NSPV_NTZS )