@@ -45,13 +45,17 @@ bool CheckProofOfTimeNWesolowski(integer D, const uint8_t* x_s, const uint8_t* p
4545{
4646 int form_size = BQFC_FORM_SIZE;
4747 int segment_len = 8 + B_bytes + form_size;
48+ // Enforce all invariants and bounds before the loop
49+ if (form_size <= 0 ) return false ;
50+ if (depth < 0 || proof_blob_len != 2 * form_size + depth * segment_len)
51+ return false ;
52+ if (x_s == nullptr || proof_blob == nullptr )
53+ return false ;
54+
55+ // All accesses in the loop are now safe
4856 int i = proof_blob_len - segment_len;
4957 form x = DeserializeForm (D, x_s, form_size);
5058
51- if (proof_blob_len != 2 * form_size + depth * segment_len)
52- return false ;
53-
54- // Loop depth times
5559 bool is_valid = false ;
5660 for (; i >= 2 * form_size; i -= segment_len) {
5761 uint64_t segment_iters = BytesToInt64 (&proof_blob[i]);
@@ -68,6 +72,7 @@ bool CheckProofOfTimeNWesolowski(integer D, const uint8_t* x_s, const uint8_t* p
6872 iterations -= segment_iters;
6973 }
7074
75+ // Final forms are guaranteed to be in-bounds
7176 VerifyWesolowskiProof (D, x,
7277 DeserializeForm (D, proof_blob, form_size),
7378 DeserializeForm (D, &proof_blob[form_size], form_size),
@@ -79,6 +84,11 @@ bool CheckProofOfTimeNWesolowski(integer D, const uint8_t* x_s, const uint8_t* p
7984bool CheckProofOfTimeNWesolowskiCommon (integer& D, form& x, const uint8_t * proof_blob, int32_t proof_blob_len, uint64_t & iterations, int last_segment, bool skip_check = false ) {
8085 int form_size = BQFC_FORM_SIZE;
8186 int segment_len = 8 + B_bytes + form_size;
87+ if (proof_blob == nullptr ) return false ;
88+ if (last_segment < 0 || proof_blob_len < 0 ) return false ;
89+ if (proof_blob_len < last_segment) return false ;
90+ if ((proof_blob_len - last_segment) % segment_len != 0 )
91+ return false ;
8292 int i = proof_blob_len - segment_len;
8393 PulmarkReducer reducer;
8494
@@ -110,6 +120,7 @@ bool CheckProofOfTimeNWesolowskiCommon(integer& D, form& x, const uint8_t* proof
110120std::pair<bool , std::vector<uint8_t >> CheckProofOfTimeNWesolowskiWithB (integer D, integer B, const uint8_t * x_s, const uint8_t * proof_blob, int32_t proof_blob_len, uint64_t iterations, int32_t depth) {
111121 int form_size = BQFC_FORM_SIZE;
112122 int segment_len = 8 + B_bytes + form_size;
123+ if (x_s == nullptr || proof_blob == nullptr ) return {false , {}};
113124 form x = DeserializeForm (D, x_s, form_size);
114125 std::vector<uint8_t > result;
115126 if (proof_blob_len != form_size + depth * segment_len) {
@@ -119,6 +130,7 @@ std::pair<bool, std::vector<uint8_t>> CheckProofOfTimeNWesolowskiWithB(integer D
119130 if (is_valid == false ) {
120131 return {false , result};
121132 }
133+ if (form_size > proof_blob_len) return {false , result};
122134 form proof = DeserializeForm (D, proof_blob, form_size);
123135 form y_result;
124136 if (VerifyWesoSegment (D, x, proof, B, iterations, y_result) == -1 ) {
@@ -129,10 +141,10 @@ std::pair<bool, std::vector<uint8_t>> CheckProofOfTimeNWesolowskiWithB(integer D
129141 return {true , result};
130142}
131143
132- // TODO: Perhaps move?
133144integer GetBFromProof (integer D, const uint8_t * x_s, const uint8_t * proof_blob, int32_t proof_blob_len, uint64_t iterations, int32_t depth) {
134145 int form_size = BQFC_FORM_SIZE;
135146 int segment_len = 8 + B_bytes + form_size;
147+ if (x_s == nullptr || proof_blob == nullptr ) throw std::runtime_error (" Invalid proof." );
136148 form x = DeserializeForm (D, x_s, form_size);
137149 if (proof_blob_len != 2 * form_size + depth * segment_len) {
138150 throw std::runtime_error (" Invalid proof." );
@@ -141,6 +153,7 @@ integer GetBFromProof(integer D, const uint8_t* x_s, const uint8_t* proof_blob,
141153 if (is_valid == false ) {
142154 throw std::runtime_error (" Invalid proof." );
143155 }
156+ if (form_size > proof_blob_len) throw std::runtime_error (" Invalid proof." );
144157 form y = DeserializeForm (D, proof_blob, form_size);
145158 return GetB (D, x, y);
146159}
0 commit comments