Repository navigation
Conversation
Adresses ” -Wshorten-64-to-32” Clang warnings.
wenzeslaus
left a comment
There was a problem hiding this comment.
The truncated lengths are used to allocate buffers, so when a length does not fit in int, the buffer is not enlarged. I suggest that lengths stay size_t as returned by strlen() and are checked against INT_MAX (like in #7950) where they enter the int-based dbmi API, i.e., db_malloc() and db_enlarge_string(). When the check fails, the code should fail like the surrounding code, ideally with a memory error. The details below and the inline suggestions are AI generated.
Details (AI generated)
In #8023, the same kind of cast was accepted because HTML_Text() is not reachable. The dbmi functions are used in live code; for example, db_append_string() is called from 66 C files, some of them in loops building SQL statements.
What happens when a length does not fit in int:
set_string()anddb_append_string(): the wrappedlenis negative or small, sox->nalloc < lenindb_enlarge_string()is false and nothing is reallocated.strcpy()orstrcat()then writes the whole string past the end of the buffer.db_store(): a negative length becomes a 1-byte allocation, becausedb_malloc()turnsn <= 0into 1, andstrcpy()writes past it.db_dirent():db_malloc((int)path_len)allocates from the truncated value, whilesnprintf(path, path_len, ...)writes up to the fullpath_len.db__send_string(): a negative length is converted to a hugesize_tindb__send(), which reads past the end ofs. A positive truncated length sends the string without its terminating null byte.
The PR currently mixes approaches: set_string() keeps int and casts strlen() right away, db_append_string() switches to size_t but casts at the call without a check, and dirent.c and xdrstring.c cast right away. With the rule above, each place gets:
| Place | Type | int boundary |
Check |
|---|---|---|---|
set_string() |
int -> size_t |
db_enlarge_string() |
yes, in the copy branch where len is used |
db_append_string() |
size_t (as in the PR) |
db_enlarge_string() |
yes |
db_store() |
new size_t len |
db_malloc() |
yes |
db__send_string() |
size_t for the computation, int len kept for sending |
sent length | yes |
db_dirent() len, max |
int -> size_t |
none, max only goes into the size_t path_len |
no, and no cast |
db_dirent() path_len |
size_t (as in the PR) |
db_malloc() |
yes |
The checks fail the same way a real allocation failure does (db_memory_error(), then NULL or DB_MEMORY_ERR), so callers already handle them. The one exception is db__send_string(), which fails like its send errors (db_protocol_error(), DB_PROTOCOL_ERR).
The suggested code was applied to the files of this PR and compiled with clang 18 using -Wshorten-64-to-32 -Wconversion. No new warnings appear, and INT_MAX needs <limits.h> in each file.
| } | ||
|
|
||
| len = strlen(s) + 1; | ||
| len = (int)strlen(s) + 1; |
There was a problem hiding this comment.
With size_t len; at the top of set_string():
len = strlen(s) + 1;
if (copy) {
if (len > INT_MAX) {
db_memory_error();
return DB_MEMORY_ERR;
}
stat = db_enlarge_string(x, (int)len);|
|
||
| len = strlen(db_get_string(x)) + strlen(s) + 1; | ||
| stat = db_enlarge_string(x, len); | ||
| stat = db_enlarge_string(x, (int)len); |
There was a problem hiding this comment.
| stat = db_enlarge_string(x, (int)len); | |
| if (len > INT_MAX) { | |
| db_memory_error(); | |
| return DB_MEMORY_ERR; | |
| } | |
| stat = db_enlarge_string(x, (int)len); |
| char *a; | ||
|
|
||
| a = db_malloc(strlen(s) + 1); | ||
| a = db_malloc((int)strlen(s) + 1); |
There was a problem hiding this comment.
char *a;
size_t len = strlen(s) + 1;
if (len > INT_MAX) {
db_memory_error();
return NULL;
}
a = db_malloc((int)len);| int stat = DB_OK; | ||
| const char *s = db_get_string(x); | ||
| int len = s ? strlen(s) + 1 : 1; | ||
| int len = s ? (int)strlen(s) + 1 : 1; |
There was a problem hiding this comment.
The sent length stays int, so compute it as size_t and fail like the send errors below:
size_t size = s ? strlen(s) + 1 : 1;
int len;
if (size > INT_MAX) {
db_protocol_error();
return DB_PROTOCOL_ERR;
}
len = (int)size;|
|
||
| size_t path_len = strlen(dirname) + max + 2; // extra 2 for / and NULL | ||
| path = db_malloc(path_len); | ||
| path = db_malloc((int)path_len); |
There was a problem hiding this comment.
len and max can be size_t without a cast, since max only goes into path_len. path_len itself needs the check:
| path = db_malloc((int)path_len); | |
| if (path_len > INT_MAX) { | |
| db_memory_error(); | |
| closedir(dp); | |
| return (dbDirent *)NULL; | |
| } | |
| path = db_malloc((int)path_len); |
Adresses ” -Wshorten-64-to-32” Clang warnings.