Commit a0d08c1
committed
gfx/gfx_thumbnail: fix four heap-safety issues found during audit pass
Four independent issues found during a focused audit of gfx/
gfx_thumbnail.c, the subsystem touched by all four menu drivers
(xmb, ozone, materialui, rgui). Same audit class as the recent
xmb (9a27e66), ozone (d56c728), and materialui (d5e598a) commits.
* gfx_thumbnail_get_path: missing break on LEFT case
(gfx/gfx_thumbnail.c)
The switch in gfx_thumbnail_get_path() that selects which path
to return based on thumbnail_id is missing a `break` after the
GFX_THUMBNAIL_LEFT case. When a caller asks for the LEFT
thumbnail and *path_data->left_path is empty, control falls
through to GFX_THUMBNAIL_ICON; if *path_data->icon_path is
populated, the function returns the icon path *as if it were
the left thumbnail*. The caller then loads the icon as the
left thumbnail texture.
Wrong-content substitution rather than memory corruption, but
silent and reachable on any menu where left thumbnails are
unset but icons are configured (the default for most playlist
configurations on xmb/ozone/materialui). Add the missing
break.
* gfx_thumbnail_get_content_dir: stack buffer overflow on long
directory paths (gfx/gfx_thumbnail.c)
The function extracts the basename of the directory portion of
path_data->content_path by copying that prefix into a local
tmp_buf[NAME_MAX_LENGTH] and then calling
path_basename_nocompression() on the copy. The strlcpy size
passed is the directory-portion length _len, which is bounded
only by `_len < PATH_MAX_LENGTH` (i.e. up to 2047) -- but
tmp_buf is only NAME_MAX_LENGTH (256) bytes. Whenever the
directory portion exceeds 255 chars, strlcpy writes up to
_len-1 bytes into the smaller tmp_buf and corrupts the stack
past it.
Reachable on systems with deep folder hierarchies; content_path
is set from runtime_content_path_basename and other content
paths capped at PATH_MAX_LENGTH, so 500+ char directory
prefixes are entirely plausible (a savefile path nested under
the user's home directory plus a deep ROM organisation
scheme).
Fix: anchor the copy at the latest position that still lets
the directory's last segment fit in tmp_buf, then take the
basename from there. We never needed the full prefix in
tmp_buf -- only its tail -- so dropping the leading bytes when
_len > sizeof(tmp_buf) gives the same answer without the
overflow.
* gfx_savestate_thumbnail_get_path: _len underflow in path
build (gfx/gfx_thumbnail.c)
Same unsafe pattern that the recent strlcpy_append sweep
(78c52ab / 25ade82 / e446242 / d5e598a) was created to
replace, applied here to a mixed strlcpy + snprintf chain:
_len = strlcpy(s, state_name, len);
if (state_slot > 0)
_len += snprintf(s + _len, len - _len, "%d", state_slot);
...
strlcpy(s + _len, FILE_PATH_PNG_EXTENSION, len - _len);
Both strlcpy and snprintf return their would-be length on
truncation, so when state_name approaches @len, _len overshoots
@len, the next `len - _len` subtraction underflows size_t to
~SIZE_MAX, and subsequent calls treat the destination as
essentially infinite.
Reachable: state_name is runloop_st->name.savestate which is
sized PATH_MAX_LENGTH; on a deep ROM directory the savestate
name itself can fill the buffer, and the slot suffix or .png
extension push the running total past @len.
Add explicit truncation guards after each step so the chain
stays inside the buffer. Also add the missing `!s || !len`
guard at the top -- the historical s[0] = '\0' before the
NULL check was a latent NULL-deref.
* gfx_thumbnail_path_init: malloc -> calloc to zero
playlist_index (gfx/gfx_thumbnail.c)
gfx_thumbnail_path_init() allocates the path_data struct via
malloc and then calls gfx_thumbnail_path_reset(), which
resets the string buffers and the three playlist_*_mode
fields but leaves playlist_index untouched -- garbage from
malloc until the first set_content_*() call writes it. Read
sites in xmb (xmb_set_title at xmb.c:2566 and the related
fallback at xmb.c:7462) sample
thumbnail_path_data->playlist_index before any setter has
necessarily run, then pass it to playlist_get_index(). The
callee bounds-checks against the playlist's size, so a
garbage index just produces a stale pl_entry rather than a
crash, but the code is latently UB.
Switch to calloc. Cheaper than touching path_reset's API
and forecloses the issue for any future read site that
doesn't replicate the bounds-check defence.1 parent d5e598a commit a0d08c1
1 file changed
Lines changed: 67 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
300 | 300 | | |
301 | 301 | | |
302 | 302 | | |
| 303 | + | |
303 | 304 | | |
304 | 305 | | |
305 | 306 | | |
| |||
1316 | 1317 | | |
1317 | 1318 | | |
1318 | 1319 | | |
| 1320 | + | |
| 1321 | + | |
| 1322 | + | |
| 1323 | + | |
| 1324 | + | |
| 1325 | + | |
| 1326 | + | |
| 1327 | + | |
| 1328 | + | |
| 1329 | + | |
| 1330 | + | |
| 1331 | + | |
1319 | 1332 | | |
1320 | | - | |
| 1333 | + | |
1321 | 1334 | | |
1322 | 1335 | | |
1323 | 1336 | | |
| |||
1915 | 1928 | | |
1916 | 1929 | | |
1917 | 1930 | | |
| 1931 | + | |
1918 | 1932 | | |
1919 | 1933 | | |
1920 | 1934 | | |
1921 | 1935 | | |
1922 | 1936 | | |
1923 | 1937 | | |
1924 | 1938 | | |
1925 | | - | |
| 1939 | + | |
| 1940 | + | |
| 1941 | + | |
| 1942 | + | |
| 1943 | + | |
| 1944 | + | |
| 1945 | + | |
| 1946 | + | |
| 1947 | + | |
| 1948 | + | |
| 1949 | + | |
| 1950 | + | |
| 1951 | + | |
| 1952 | + | |
| 1953 | + | |
| 1954 | + | |
| 1955 | + | |
| 1956 | + | |
1926 | 1957 | | |
1927 | 1958 | | |
1928 | 1959 | | |
| |||
1934 | 1965 | | |
1935 | 1966 | | |
1936 | 1967 | | |
| 1968 | + | |
| 1969 | + | |
| 1970 | + | |
1937 | 1971 | | |
1938 | 1972 | | |
1939 | 1973 | | |
1940 | 1974 | | |
1941 | 1975 | | |
1942 | 1976 | | |
1943 | 1977 | | |
| 1978 | + | |
| 1979 | + | |
| 1980 | + | |
| 1981 | + | |
| 1982 | + | |
| 1983 | + | |
| 1984 | + | |
| 1985 | + | |
| 1986 | + | |
| 1987 | + | |
| 1988 | + | |
| 1989 | + | |
| 1990 | + | |
| 1991 | + | |
| 1992 | + | |
| 1993 | + | |
| 1994 | + | |
| 1995 | + | |
1944 | 1996 | | |
1945 | | - | |
| 1997 | + | |
| 1998 | + | |
| 1999 | + | |
| 2000 | + | |
| 2001 | + | |
| 2002 | + | |
| 2003 | + | |
| 2004 | + | |
1946 | 2005 | | |
1947 | | - | |
| 2006 | + | |
| 2007 | + | |
| 2008 | + | |
| 2009 | + | |
| 2010 | + | |
1948 | 2011 | | |
1949 | 2012 | | |
1950 | 2013 | | |
0 commit comments