mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 03:29:43 -10:00
config_file: drop the redundant stat before reading a config
config_file_new_from_path_to_string() guarded the read with path_is_valid(), a stat, and then called filestream_read_file(), which opens the file itself and returns 0 when it cannot. The stat repeated the lookup the open already does. No caller can tell the two apart: a path that fails path_is_valid and one that fails to open both leave the function through the same NULL return, and none of the ~46 callers inspects why. So the stat's result was never visible - pure duplicate work. Removing it also closes the small window between the stat and the open in which the file could be replaced or deleted, the usual time-of-check/time-of-use gap. Behaviour is unchanged: a valid file parses, a missing file and a NULL path both return NULL, since filestream_read_file() and filestream_open() already reject both. Verified against all three. The cost is immaterial - about a third of a millisecond across 300 core-info files on a warm cache - so this is a simplification and a TOCTOU removal, not a speedup. It matters a little more where a stat is dear: cold cache, network shares, the slow flash on handhelds.
This commit is contained in:
1 parent
285f966632
commit
41157ba829
1 file changed
+19
-15
@@ -828,24 +828,28 @@ config_file_t *config_file_new_from_string(char *from_string,
|
||||
|
||||
config_file_t *config_file_new_from_path_to_string(const char *path)
|
||||
{
|
||||
if (path_is_valid(path))
|
||||
uint8_t *ret_buf = NULL;
|
||||
int64_t length = 0;
|
||||
|
||||
/* No path_is_valid() first: filestream_read_file() opens the file
|
||||
* itself and returns 0 when it cannot, so a preceding stat only
|
||||
* repeats the lookup the open already does - and no caller can see
|
||||
* its result, since a missing file and an unreadable one both land
|
||||
* on the same NULL return. Dropping it also closes the window
|
||||
* between the stat and the open in which the file could change. */
|
||||
if (filestream_read_file(path, (void**)&ret_buf, &length))
|
||||
{
|
||||
uint8_t *ret_buf = NULL;
|
||||
int64_t length = 0;
|
||||
if (filestream_read_file(path, (void**)&ret_buf, &length))
|
||||
{
|
||||
config_file_t *conf = NULL;
|
||||
/* Note: 'ret_buf' is not used outside this
|
||||
* function - we do not care that it will be
|
||||
* modified by config_file_new_from_string() */
|
||||
if (length >= 0)
|
||||
conf = config_file_new_from_string((char*)ret_buf, path);
|
||||
config_file_t *conf = NULL;
|
||||
/* Note: 'ret_buf' is not used outside this
|
||||
* function - we do not care that it will be
|
||||
* modified by config_file_new_from_string() */
|
||||
if (length >= 0)
|
||||
conf = config_file_new_from_string((char*)ret_buf, path);
|
||||
|
||||
if ((void*)ret_buf)
|
||||
free((void*)ret_buf);
|
||||
if ((void*)ret_buf)
|
||||
free((void*)ret_buf);
|
||||
|
||||
return conf;
|
||||
}
|
||||
return conf;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
Reference in new issue
Block a user