Fossil SCM

Detect integer overflow in the blob_is_int() and blob_is_int64() routines.

drh 2026-07-25 10:25 UTC trunk
Commit 052390edaf04a5f587def306f13a7cbfc7c2cf57c76b83824fd5cf0c617eb7f5
1 file changed +49 -20
+49 -20
--- src/blob.c
+++ src/blob.c
@@ -1048,47 +1048,76 @@
10481048
int blob_is_filename(Blob *pBlob){
10491049
return file_is_simple_pathname(blob_str(pBlob), 1);
10501050
}
10511051
10521052
/*
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.
10551056
*/
10561057
int blob_is_int(Blob *pBlob, int *pValue){
10571058
const char *z = blob_buffer(pBlob);
1058
- int i, n, c, v;
1059
+ int i, n, c;
1060
+ sqlite3_uint64 v;
10591061
n = blob_size(pBlob);
10601062
v = 0;
10611063
for(i=0; i<n && (c = z[i])!=0 && c>='0' && c<='9'; i++){
10621064
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
+ }
10631092
}
10641093
if( i==n ){
1065
- *pValue = v;
1094
+ *pValue = (sqlite3_int64)v;
10661095
return 1;
10671096
}else{
10681097
return 0;
10691098
}
10701099
}
10711100
10721101
/*
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.
10751106
*/
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);
10901119
}
10911120
}
10921121
10931122
/*
10941123
** Zero or reset an array of Blobs.
10951124
--- 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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button