Fossil SCM
Check bounds and type for HTTP Content-length header. Also reject reply with two different Content-Length values. From libfossil.
Commit
4df4f6c1dfa9e6af8e462572bfae90884557bd59bf3e7f528705c0d4f27ea675
Parent
33118a37bd6c360…
1 file changed
+22
-1
+22
-1
| --- src/http.c | ||
| +++ src/http.c | ||
| @@ -614,12 +614,33 @@ | ||
| 614 | 614 | goto write_err; |
| 615 | 615 | } |
| 616 | 616 | if( iHttpVersion<0 ) iHttpVersion = 1; |
| 617 | 617 | closeConnection = 0; |
| 618 | 618 | }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){ |
| 619 | + /* The value is one or more digits, optionally followed by | |
| 620 | + ** spaces, and fits in an int. Any other value is an error, and | |
| 621 | + ** so is a second Content-Length with a different value. */ | |
| 622 | + sqlite3_int64 n = 0; | |
| 623 | + int iStart; | |
| 619 | 624 | for(i=15; fossil_isspace(zLine[i]); i++){} |
| 620 | - iLength = atoi(&zLine[i]); | |
| 625 | + for(iStart=i; fossil_isdigit(zLine[i]) && n<=0x7fffffff; i++){ | |
| 626 | + n = n*10 + zLine[i] - '0'; | |
| 627 | + } | |
| 628 | + if( i==iStart || n>0x7fffffff ){ | |
| 629 | + fossil_warning("server sent a bad content-length: %s", zLine); | |
| 630 | + goto write_err; | |
| 631 | + } | |
| 632 | + for(; fossil_isspace(zLine[i]); i++){} | |
| 633 | + if( zLine[i]!=0 ){ | |
| 634 | + fossil_warning("server sent a bad content-length: %s", zLine); | |
| 635 | + goto write_err; | |
| 636 | + } | |
| 637 | + if( iLength>=0 && iLength!=(int)n ){ | |
| 638 | + fossil_warning("server sent two different content-length values"); | |
| 639 | + goto write_err; | |
| 640 | + } | |
| 641 | + iLength = (int)n; | |
| 621 | 642 | }else if( fossil_strnicmp(zLine, "transfer-encoding:", 18)==0 ){ |
| 622 | 643 | /* Fossil never sends a "transfer-encoding:" request header, so we may |
| 623 | 644 | ** reject any encoding other than "chunked", including "gzip, chunked", |
| 624 | 645 | ** "superchunked", "deflate" etc. */ |
| 625 | 646 | int bOk = 0; |
| 626 | 647 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -614,12 +614,33 @@ | |
| 614 | goto write_err; |
| 615 | } |
| 616 | if( iHttpVersion<0 ) iHttpVersion = 1; |
| 617 | closeConnection = 0; |
| 618 | }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){ |
| 619 | for(i=15; fossil_isspace(zLine[i]); i++){} |
| 620 | iLength = atoi(&zLine[i]); |
| 621 | }else if( fossil_strnicmp(zLine, "transfer-encoding:", 18)==0 ){ |
| 622 | /* Fossil never sends a "transfer-encoding:" request header, so we may |
| 623 | ** reject any encoding other than "chunked", including "gzip, chunked", |
| 624 | ** "superchunked", "deflate" etc. */ |
| 625 | int bOk = 0; |
| 626 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -614,12 +614,33 @@ | |
| 614 | goto write_err; |
| 615 | } |
| 616 | if( iHttpVersion<0 ) iHttpVersion = 1; |
| 617 | closeConnection = 0; |
| 618 | }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){ |
| 619 | /* The value is one or more digits, optionally followed by |
| 620 | ** spaces, and fits in an int. Any other value is an error, and |
| 621 | ** so is a second Content-Length with a different value. */ |
| 622 | sqlite3_int64 n = 0; |
| 623 | int iStart; |
| 624 | for(i=15; fossil_isspace(zLine[i]); i++){} |
| 625 | for(iStart=i; fossil_isdigit(zLine[i]) && n<=0x7fffffff; i++){ |
| 626 | n = n*10 + zLine[i] - '0'; |
| 627 | } |
| 628 | if( i==iStart || n>0x7fffffff ){ |
| 629 | fossil_warning("server sent a bad content-length: %s", zLine); |
| 630 | goto write_err; |
| 631 | } |
| 632 | for(; fossil_isspace(zLine[i]); i++){} |
| 633 | if( zLine[i]!=0 ){ |
| 634 | fossil_warning("server sent a bad content-length: %s", zLine); |
| 635 | goto write_err; |
| 636 | } |
| 637 | if( iLength>=0 && iLength!=(int)n ){ |
| 638 | fossil_warning("server sent two different content-length values"); |
| 639 | goto write_err; |
| 640 | } |
| 641 | iLength = (int)n; |
| 642 | }else if( fossil_strnicmp(zLine, "transfer-encoding:", 18)==0 ){ |
| 643 | /* Fossil never sends a "transfer-encoding:" request header, so we may |
| 644 | ** reject any encoding other than "chunked", including "gzip, chunked", |
| 645 | ** "superchunked", "deflate" etc. */ |
| 646 | int bOk = 0; |
| 647 |