Fossil SCM
Detect integer overflow in the blob_is_int() and blob_is_int64() routines.
Commit
052390edaf04a5f587def306f13a7cbfc7c2cf57c76b83824fd5cf0c617eb7f5
Parent
4816e03320c6647…
1 file changed
+49
-20
+49
-20
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -1048,47 +1048,76 @@ | ||
| 1048 | 1048 | int blob_is_filename(Blob *pBlob){ |
| 1049 | 1049 | return file_is_simple_pathname(blob_str(pBlob), 1); |
| 1050 | 1050 | } |
| 1051 | 1051 | |
| 1052 | 1052 | /* |
| 1053 | -** Return true if the blob contains a valid 32-bit integer. Store | |
| 1054 | -** the integer value in *pValue. | |
| 1053 | +** Return true if the blob contains a valid non-negative 32-bit integer | |
| 1054 | +** and store the integer value in *pValue. If the blob is not a valid | |
| 1055 | +** non-negative 32-bit integer, return false and leave *pValue unchanged. | |
| 1055 | 1056 | */ |
| 1056 | 1057 | int blob_is_int(Blob *pBlob, int *pValue){ |
| 1057 | 1058 | const char *z = blob_buffer(pBlob); |
| 1058 | - int i, n, c, v; | |
| 1059 | + int i, n, c; | |
| 1060 | + sqlite3_uint64 v; | |
| 1059 | 1061 | n = blob_size(pBlob); |
| 1060 | 1062 | v = 0; |
| 1061 | 1063 | for(i=0; i<n && (c = z[i])!=0 && c>='0' && c<='9'; i++){ |
| 1062 | 1064 | v = v*10 + c - '0'; |
| 1065 | + if( v>0x7fffffff ) return 0; | |
| 1066 | + } | |
| 1067 | + if( i==n ){ | |
| 1068 | + *pValue = (int)v; | |
| 1069 | + return 1; | |
| 1070 | + }else{ | |
| 1071 | + return 0; | |
| 1072 | + } | |
| 1073 | +} | |
| 1074 | + | |
| 1075 | +/* | |
| 1076 | +** Return true if the blob contains a valid non-negative 64-bit integer | |
| 1077 | +** and store the integer value in *pValue. If the blob is not a valid | |
| 1078 | +** non-negative 64-bit integer, return false and leave *pValue unchanged. | |
| 1079 | +*/ | |
| 1080 | +int blob_is_int64(Blob *pBlob, sqlite3_int64 *pValue){ | |
| 1081 | + const char *z = blob_buffer(pBlob); | |
| 1082 | + int i, n, c; | |
| 1083 | + sqlite3_uint64 v; | |
| 1084 | + n = blob_size(pBlob); | |
| 1085 | + v = 0; | |
| 1086 | + for(i=0; i<n && (c = z[i])!=0 && c>='0' && c<='9'; i++){ | |
| 1087 | + if( v<922337203685477580ULL || (v==922337203685477580ULL && c<='7') ){ | |
| 1088 | + v = v*10 + c - '0'; | |
| 1089 | + }else{ | |
| 1090 | + return 0; | |
| 1091 | + } | |
| 1063 | 1092 | } |
| 1064 | 1093 | if( i==n ){ |
| 1065 | - *pValue = v; | |
| 1094 | + *pValue = (sqlite3_int64)v; | |
| 1066 | 1095 | return 1; |
| 1067 | 1096 | }else{ |
| 1068 | 1097 | return 0; |
| 1069 | 1098 | } |
| 1070 | 1099 | } |
| 1071 | 1100 | |
| 1072 | 1101 | /* |
| 1073 | -** Return true if the blob contains a valid 64-bit integer. Store | |
| 1074 | -** the integer value in *pValue. | |
| 1102 | +** COMMAND: test-atoi | |
| 1103 | +** | |
| 1104 | +** Use the blob_is_int() and blob_is_int64() routines to convert arguments | |
| 1105 | +** into integers. Used for unit testing of those routines. | |
| 1075 | 1106 | */ |
| 1076 | -int blob_is_int64(Blob *pBlob, sqlite3_int64 *pValue){ | |
| 1077 | - const char *z = blob_buffer(pBlob); | |
| 1078 | - int i, n, c; | |
| 1079 | - sqlite3_int64 v; | |
| 1080 | - n = blob_size(pBlob); | |
| 1081 | - v = 0; | |
| 1082 | - for(i=0; i<n && (c = z[i])!=0 && c>='0' && c<='9'; i++){ | |
| 1083 | - v = v*10 + c - '0'; | |
| 1084 | - } | |
| 1085 | - if( i==n ){ | |
| 1086 | - *pValue = v; | |
| 1087 | - return 1; | |
| 1088 | - }else{ | |
| 1089 | - return 0; | |
| 1107 | +void blob_is_int_cmd(void){ | |
| 1108 | + int i; | |
| 1109 | + for(i=2; i<g.argc; i++){ | |
| 1110 | + Blob x; | |
| 1111 | + int i32 = 0; | |
| 1112 | + sqlite3_int64 i64 = 0; | |
| 1113 | + int rc; | |
| 1114 | + blob_init(&x, g.argv[i], -1); | |
| 1115 | + rc = blob_is_int(&x, &i32); | |
| 1116 | + fossil_print("%20s: 32-bit %d %-10d", g.argv[i], rc, i32); | |
| 1117 | + rc = blob_is_int64(&x, &i64); | |
| 1118 | + fossil_print(" 64-bit %d %lld\n", rc, i64); | |
| 1090 | 1119 | } |
| 1091 | 1120 | } |
| 1092 | 1121 | |
| 1093 | 1122 | /* |
| 1094 | 1123 | ** Zero or reset an array of Blobs. |
| 1095 | 1124 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -1048,47 +1048,76 @@ | |
| 1048 | int blob_is_filename(Blob *pBlob){ |
| 1049 | return file_is_simple_pathname(blob_str(pBlob), 1); |
| 1050 | } |
| 1051 | |
| 1052 | /* |
| 1053 | ** Return true if the blob contains a valid 32-bit integer. Store |
| 1054 | ** the integer value in *pValue. |
| 1055 | */ |
| 1056 | int blob_is_int(Blob *pBlob, int *pValue){ |
| 1057 | const char *z = blob_buffer(pBlob); |
| 1058 | int i, n, c, v; |
| 1059 | n = blob_size(pBlob); |
| 1060 | v = 0; |
| 1061 | for(i=0; i<n && (c = z[i])!=0 && c>='0' && c<='9'; i++){ |
| 1062 | v = v*10 + c - '0'; |
| 1063 | } |
| 1064 | if( i==n ){ |
| 1065 | *pValue = v; |
| 1066 | return 1; |
| 1067 | }else{ |
| 1068 | return 0; |
| 1069 | } |
| 1070 | } |
| 1071 | |
| 1072 | /* |
| 1073 | ** Return true if the blob contains a valid 64-bit integer. Store |
| 1074 | ** the integer value in *pValue. |
| 1075 | */ |
| 1076 | int blob_is_int64(Blob *pBlob, sqlite3_int64 *pValue){ |
| 1077 | const char *z = blob_buffer(pBlob); |
| 1078 | int i, n, c; |
| 1079 | sqlite3_int64 v; |
| 1080 | n = blob_size(pBlob); |
| 1081 | v = 0; |
| 1082 | for(i=0; i<n && (c = z[i])!=0 && c>='0' && c<='9'; i++){ |
| 1083 | v = v*10 + c - '0'; |
| 1084 | } |
| 1085 | if( i==n ){ |
| 1086 | *pValue = v; |
| 1087 | return 1; |
| 1088 | }else{ |
| 1089 | return 0; |
| 1090 | } |
| 1091 | } |
| 1092 | |
| 1093 | /* |
| 1094 | ** Zero or reset an array of Blobs. |
| 1095 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -1048,47 +1048,76 @@ | |
| 1048 | int blob_is_filename(Blob *pBlob){ |
| 1049 | return file_is_simple_pathname(blob_str(pBlob), 1); |
| 1050 | } |
| 1051 | |
| 1052 | /* |
| 1053 | ** Return true if the blob contains a valid non-negative 32-bit integer |
| 1054 | ** and store the integer value in *pValue. If the blob is not a valid |
| 1055 | ** non-negative 32-bit integer, return false and leave *pValue unchanged. |
| 1056 | */ |
| 1057 | int blob_is_int(Blob *pBlob, int *pValue){ |
| 1058 | const char *z = blob_buffer(pBlob); |
| 1059 | int i, n, c; |
| 1060 | sqlite3_uint64 v; |
| 1061 | n = blob_size(pBlob); |
| 1062 | v = 0; |
| 1063 | for(i=0; i<n && (c = z[i])!=0 && c>='0' && c<='9'; i++){ |
| 1064 | v = v*10 + c - '0'; |
| 1065 | if( v>0x7fffffff ) return 0; |
| 1066 | } |
| 1067 | if( i==n ){ |
| 1068 | *pValue = (int)v; |
| 1069 | return 1; |
| 1070 | }else{ |
| 1071 | return 0; |
| 1072 | } |
| 1073 | } |
| 1074 | |
| 1075 | /* |
| 1076 | ** Return true if the blob contains a valid non-negative 64-bit integer |
| 1077 | ** and store the integer value in *pValue. If the blob is not a valid |
| 1078 | ** non-negative 64-bit integer, return false and leave *pValue unchanged. |
| 1079 | */ |
| 1080 | int blob_is_int64(Blob *pBlob, sqlite3_int64 *pValue){ |
| 1081 | const char *z = blob_buffer(pBlob); |
| 1082 | int i, n, c; |
| 1083 | sqlite3_uint64 v; |
| 1084 | n = blob_size(pBlob); |
| 1085 | v = 0; |
| 1086 | for(i=0; i<n && (c = z[i])!=0 && c>='0' && c<='9'; i++){ |
| 1087 | if( v<922337203685477580ULL || (v==922337203685477580ULL && c<='7') ){ |
| 1088 | v = v*10 + c - '0'; |
| 1089 | }else{ |
| 1090 | return 0; |
| 1091 | } |
| 1092 | } |
| 1093 | if( i==n ){ |
| 1094 | *pValue = (sqlite3_int64)v; |
| 1095 | return 1; |
| 1096 | }else{ |
| 1097 | return 0; |
| 1098 | } |
| 1099 | } |
| 1100 | |
| 1101 | /* |
| 1102 | ** COMMAND: test-atoi |
| 1103 | ** |
| 1104 | ** Use the blob_is_int() and blob_is_int64() routines to convert arguments |
| 1105 | ** into integers. Used for unit testing of those routines. |
| 1106 | */ |
| 1107 | void blob_is_int_cmd(void){ |
| 1108 | int i; |
| 1109 | for(i=2; i<g.argc; i++){ |
| 1110 | Blob x; |
| 1111 | int i32 = 0; |
| 1112 | sqlite3_int64 i64 = 0; |
| 1113 | int rc; |
| 1114 | blob_init(&x, g.argv[i], -1); |
| 1115 | rc = blob_is_int(&x, &i32); |
| 1116 | fossil_print("%20s: 32-bit %d %-10d", g.argv[i], rc, i32); |
| 1117 | rc = blob_is_int64(&x, &i64); |
| 1118 | fossil_print(" 64-bit %d %lld\n", rc, i64); |
| 1119 | } |
| 1120 | } |
| 1121 | |
| 1122 | /* |
| 1123 | ** Zero or reset an array of Blobs. |
| 1124 |