I found this code on git and wanted to use it, but someone made a comment about a security bug in it. I don't seem to identify it:
int32_t read_arrbuff(FILE *f, uint32_t *arrmap) {
int32_t i = 0, n_map;
fread(&n_map, sizeof(n_map), 1, f);
if (n_map > 256)
return -1;
while (n_map--) {
fread(&arrmap[i++], sizeof(uint32_t), 1, f);
}
return n_map;
}
Taken in isolation, the problems include:
f
is not NULL.arrmap
is not NULL.fread()
was successful.fread()
was successful.-1
, regardless of whether anything worked or failed.Which of those are security problems? At some levels, all of them. In some contexts, you could assume that
f
andarrmap
are legitimate without checking. Not checking that the reads are successful, especially the first, is a serious problem. The negative values forn_map
would be a serious issue. Claiming success when every read failed would be a problem.When the loop completes,
n_map
is set to-1
(it was zero before the post-decrement). So, you return -1 on failure or success. That's not helpful. It should almost certainly return the value ofn_map
that was read from file, so the caller can tell how many values are in the array.It is usually best not to hard code a size limit like
256
into the program. The interface should include the array size and you should check against the passed array size.Working to the original interface, you could use:
You can debate whether the unilateral exits imposed by
err_syserr()
are appropriate. (The declarations and source for theerr_*()
functions is instderr.h
andstderr.c
, and is available from GitHub.)An alternative version taking the maximum array size from a function parameter is:
This version reports a specific error and returns on error. It makes semi-appropriate assertions on entry (the 256 limit is not necessarily appropriate, but is consistent with the original code).
The output is unexciting (and the same from both):