Fossil SCM
Fix several blob leaks that can lead to out of memory conditions for very large push operations. Revise the order of error messages so that simple HTTP timeout produces a better diagnostic. The HTTP trace files need to be opened in binary mode.
Commit
1e398088536c7512f0cb290a15e8b9bc33d30124
Parent
238b761afafe62e…
2 files changed
+6
-6
+6
+6
-6
| --- src/http.c | ||
| +++ src/http.c | ||
| @@ -174,19 +174,19 @@ | ||
| 174 | 174 | static int traceCnt = 0; |
| 175 | 175 | char *zOutFile; |
| 176 | 176 | FILE *out; |
| 177 | 177 | traceCnt++; |
| 178 | 178 | zOutFile = mprintf("http-request-%d.txt", traceCnt); |
| 179 | - out = fopen(zOutFile, "w"); | |
| 179 | + out = fopen(zOutFile, "wb"); | |
| 180 | 180 | if( out ){ |
| 181 | 181 | fwrite(blob_buffer(&hdr), 1, blob_size(&hdr), out); |
| 182 | 182 | fwrite(blob_buffer(&payload), 1, blob_size(&payload), out); |
| 183 | 183 | fclose(out); |
| 184 | 184 | } |
| 185 | 185 | free(zOutFile); |
| 186 | 186 | zOutFile = mprintf("http-reply-%d.txt", traceCnt); |
| 187 | - out = fopen(zOutFile, "w"); | |
| 187 | + out = fopen(zOutFile, "wb"); | |
| 188 | 188 | transport_log(out); |
| 189 | 189 | free(zOutFile); |
| 190 | 190 | } |
| 191 | 191 | |
| 192 | 192 | /* |
| @@ -253,22 +253,22 @@ | ||
| 253 | 253 | }else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){ |
| 254 | 254 | isError = 1; |
| 255 | 255 | } |
| 256 | 256 | } |
| 257 | 257 | } |
| 258 | + if( iLength<0 ){ | |
| 259 | + fossil_fatal("server did not reply"); | |
| 260 | + goto write_err; | |
| 261 | + } | |
| 258 | 262 | if( rc!=200 ){ |
| 259 | 263 | fossil_warning("\"location:\" missing from 302 redirect reply"); |
| 260 | 264 | goto write_err; |
| 261 | 265 | } |
| 262 | 266 | |
| 263 | 267 | /* |
| 264 | 268 | ** Extract the reply payload that follows the header |
| 265 | 269 | */ |
| 266 | - if( iLength<0 ){ | |
| 267 | - fossil_fatal("server did not reply"); | |
| 268 | - goto write_err; | |
| 269 | - } | |
| 270 | 270 | blob_zero(pReply); |
| 271 | 271 | blob_resize(pReply, iLength); |
| 272 | 272 | iLength = transport_receive(blob_buffer(pReply), iLength); |
| 273 | 273 | blob_resize(pReply, iLength); |
| 274 | 274 | if( isError ){ |
| 275 | 275 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -174,19 +174,19 @@ | |
| 174 | static int traceCnt = 0; |
| 175 | char *zOutFile; |
| 176 | FILE *out; |
| 177 | traceCnt++; |
| 178 | zOutFile = mprintf("http-request-%d.txt", traceCnt); |
| 179 | out = fopen(zOutFile, "w"); |
| 180 | if( out ){ |
| 181 | fwrite(blob_buffer(&hdr), 1, blob_size(&hdr), out); |
| 182 | fwrite(blob_buffer(&payload), 1, blob_size(&payload), out); |
| 183 | fclose(out); |
| 184 | } |
| 185 | free(zOutFile); |
| 186 | zOutFile = mprintf("http-reply-%d.txt", traceCnt); |
| 187 | out = fopen(zOutFile, "w"); |
| 188 | transport_log(out); |
| 189 | free(zOutFile); |
| 190 | } |
| 191 | |
| 192 | /* |
| @@ -253,22 +253,22 @@ | |
| 253 | }else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){ |
| 254 | isError = 1; |
| 255 | } |
| 256 | } |
| 257 | } |
| 258 | if( rc!=200 ){ |
| 259 | fossil_warning("\"location:\" missing from 302 redirect reply"); |
| 260 | goto write_err; |
| 261 | } |
| 262 | |
| 263 | /* |
| 264 | ** Extract the reply payload that follows the header |
| 265 | */ |
| 266 | if( iLength<0 ){ |
| 267 | fossil_fatal("server did not reply"); |
| 268 | goto write_err; |
| 269 | } |
| 270 | blob_zero(pReply); |
| 271 | blob_resize(pReply, iLength); |
| 272 | iLength = transport_receive(blob_buffer(pReply), iLength); |
| 273 | blob_resize(pReply, iLength); |
| 274 | if( isError ){ |
| 275 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -174,19 +174,19 @@ | |
| 174 | static int traceCnt = 0; |
| 175 | char *zOutFile; |
| 176 | FILE *out; |
| 177 | traceCnt++; |
| 178 | zOutFile = mprintf("http-request-%d.txt", traceCnt); |
| 179 | out = fopen(zOutFile, "wb"); |
| 180 | if( out ){ |
| 181 | fwrite(blob_buffer(&hdr), 1, blob_size(&hdr), out); |
| 182 | fwrite(blob_buffer(&payload), 1, blob_size(&payload), out); |
| 183 | fclose(out); |
| 184 | } |
| 185 | free(zOutFile); |
| 186 | zOutFile = mprintf("http-reply-%d.txt", traceCnt); |
| 187 | out = fopen(zOutFile, "wb"); |
| 188 | transport_log(out); |
| 189 | free(zOutFile); |
| 190 | } |
| 191 | |
| 192 | /* |
| @@ -253,22 +253,22 @@ | |
| 253 | }else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){ |
| 254 | isError = 1; |
| 255 | } |
| 256 | } |
| 257 | } |
| 258 | if( iLength<0 ){ |
| 259 | fossil_fatal("server did not reply"); |
| 260 | goto write_err; |
| 261 | } |
| 262 | if( rc!=200 ){ |
| 263 | fossil_warning("\"location:\" missing from 302 redirect reply"); |
| 264 | goto write_err; |
| 265 | } |
| 266 | |
| 267 | /* |
| 268 | ** Extract the reply payload that follows the header |
| 269 | */ |
| 270 | blob_zero(pReply); |
| 271 | blob_resize(pReply, iLength); |
| 272 | iLength = transport_receive(blob_buffer(pReply), iLength); |
| 273 | blob_resize(pReply, iLength); |
| 274 | if( isError ){ |
| 275 |
+6
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -127,14 +127,16 @@ | ||
| 127 | 127 | blob_zero(&content); |
| 128 | 128 | blob_zero(&hash); |
| 129 | 129 | blob_extract(pXfer->pIn, n, &content); |
| 130 | 130 | if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){ |
| 131 | 131 | /* Ignore files that have been shunned */ |
| 132 | + blob_reset(&content); | |
| 132 | 133 | return; |
| 133 | 134 | } |
| 134 | 135 | if( isPriv && !g.perm.Private ){ |
| 135 | 136 | /* Do not accept private files if not authorized */ |
| 137 | + blob_reset(&content); | |
| 136 | 138 | return; |
| 137 | 139 | } |
| 138 | 140 | if( cloneFlag ){ |
| 139 | 141 | if( pXfer->nToken==4 ){ |
| 140 | 142 | srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv); |
| @@ -156,10 +158,12 @@ | ||
| 156 | 158 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 157 | 159 | 0, isPriv); |
| 158 | 160 | pXfer->nDanglingFile++; |
| 159 | 161 | db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); |
| 160 | 162 | if( !isPriv ) content_make_public(rid); |
| 163 | + blob_reset(&src); | |
| 164 | + blob_reset(&content); | |
| 161 | 165 | return; |
| 162 | 166 | } |
| 163 | 167 | pXfer->nDeltaRcvd++; |
| 164 | 168 | blob_delta_apply(&src, &content, &next); |
| 165 | 169 | blob_reset(&src); |
| @@ -235,10 +239,11 @@ | ||
| 235 | 239 | } |
| 236 | 240 | blob_zero(&content); |
| 237 | 241 | blob_extract(pXfer->pIn, szC, &content); |
| 238 | 242 | if( uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){ |
| 239 | 243 | /* Ignore files that have been shunned */ |
| 244 | + blob_reset(&content); | |
| 240 | 245 | return; |
| 241 | 246 | } |
| 242 | 247 | if( pXfer->nToken==5 ){ |
| 243 | 248 | srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv); |
| 244 | 249 | pXfer->nDeltaRcvd++; |
| @@ -420,10 +425,11 @@ | ||
| 420 | 425 | blob_append(pXfer->pOut, blob_buffer(&content), size); |
| 421 | 426 | pXfer->nFileSent++; |
| 422 | 427 | }else{ |
| 423 | 428 | pXfer->nDeltaSent++; |
| 424 | 429 | } |
| 430 | + blob_reset(&content); | |
| 425 | 431 | } |
| 426 | 432 | remote_has(rid); |
| 427 | 433 | blob_reset(&uuid); |
| 428 | 434 | #if 0 |
| 429 | 435 | if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){ |
| 430 | 436 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -127,14 +127,16 @@ | |
| 127 | blob_zero(&content); |
| 128 | blob_zero(&hash); |
| 129 | blob_extract(pXfer->pIn, n, &content); |
| 130 | if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){ |
| 131 | /* Ignore files that have been shunned */ |
| 132 | return; |
| 133 | } |
| 134 | if( isPriv && !g.perm.Private ){ |
| 135 | /* Do not accept private files if not authorized */ |
| 136 | return; |
| 137 | } |
| 138 | if( cloneFlag ){ |
| 139 | if( pXfer->nToken==4 ){ |
| 140 | srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv); |
| @@ -156,10 +158,12 @@ | |
| 156 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 157 | 0, isPriv); |
| 158 | pXfer->nDanglingFile++; |
| 159 | db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); |
| 160 | if( !isPriv ) content_make_public(rid); |
| 161 | return; |
| 162 | } |
| 163 | pXfer->nDeltaRcvd++; |
| 164 | blob_delta_apply(&src, &content, &next); |
| 165 | blob_reset(&src); |
| @@ -235,10 +239,11 @@ | |
| 235 | } |
| 236 | blob_zero(&content); |
| 237 | blob_extract(pXfer->pIn, szC, &content); |
| 238 | if( uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){ |
| 239 | /* Ignore files that have been shunned */ |
| 240 | return; |
| 241 | } |
| 242 | if( pXfer->nToken==5 ){ |
| 243 | srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv); |
| 244 | pXfer->nDeltaRcvd++; |
| @@ -420,10 +425,11 @@ | |
| 420 | blob_append(pXfer->pOut, blob_buffer(&content), size); |
| 421 | pXfer->nFileSent++; |
| 422 | }else{ |
| 423 | pXfer->nDeltaSent++; |
| 424 | } |
| 425 | } |
| 426 | remote_has(rid); |
| 427 | blob_reset(&uuid); |
| 428 | #if 0 |
| 429 | if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){ |
| 430 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -127,14 +127,16 @@ | |
| 127 | blob_zero(&content); |
| 128 | blob_zero(&hash); |
| 129 | blob_extract(pXfer->pIn, n, &content); |
| 130 | if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){ |
| 131 | /* Ignore files that have been shunned */ |
| 132 | blob_reset(&content); |
| 133 | return; |
| 134 | } |
| 135 | if( isPriv && !g.perm.Private ){ |
| 136 | /* Do not accept private files if not authorized */ |
| 137 | blob_reset(&content); |
| 138 | return; |
| 139 | } |
| 140 | if( cloneFlag ){ |
| 141 | if( pXfer->nToken==4 ){ |
| 142 | srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv); |
| @@ -156,10 +158,12 @@ | |
| 158 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 159 | 0, isPriv); |
| 160 | pXfer->nDanglingFile++; |
| 161 | db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); |
| 162 | if( !isPriv ) content_make_public(rid); |
| 163 | blob_reset(&src); |
| 164 | blob_reset(&content); |
| 165 | return; |
| 166 | } |
| 167 | pXfer->nDeltaRcvd++; |
| 168 | blob_delta_apply(&src, &content, &next); |
| 169 | blob_reset(&src); |
| @@ -235,10 +239,11 @@ | |
| 239 | } |
| 240 | blob_zero(&content); |
| 241 | blob_extract(pXfer->pIn, szC, &content); |
| 242 | if( uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){ |
| 243 | /* Ignore files that have been shunned */ |
| 244 | blob_reset(&content); |
| 245 | return; |
| 246 | } |
| 247 | if( pXfer->nToken==5 ){ |
| 248 | srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv); |
| 249 | pXfer->nDeltaRcvd++; |
| @@ -420,10 +425,11 @@ | |
| 425 | blob_append(pXfer->pOut, blob_buffer(&content), size); |
| 426 | pXfer->nFileSent++; |
| 427 | }else{ |
| 428 | pXfer->nDeltaSent++; |
| 429 | } |
| 430 | blob_reset(&content); |
| 431 | } |
| 432 | remote_has(rid); |
| 433 | blob_reset(&uuid); |
| 434 | #if 0 |
| 435 | if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){ |
| 436 |