mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
vfs: hang vfs_cdrom_t off the file handle instead of embedding it
vfs_cdrom_t was an inline member at the head of libretro_vfs_implementation_file. It carries a 2352-byte sector cache (last_frame) plus the cue sheet cursor, so in a build with HAVE_CDROM every open file handle cost 2464 bytes rather than 72 - a 34x inflation for state that only cdrom:// handles ever read. Measured offsets, x86-64, HAVE_CDROM, before and after: sizeof 2464 -> 80 mappos 2400 -> 8 mapsize 2408 -> 16 mapped 2440 -> 48 hints 2452 -> 60 The footprint is the real motivation. The layout is a secondary win: the mmap read path in retro_vfs_file_read_impl() touches hints, mappos, mapsize and mapped, which sat at 2400..2452 and therefore straddled two 64-byte lines; they now share the first line with the rest of the hot set, matching what a build without HAVE_CDROM already got. That is worth a few cycles against a memcpy, not more - this is I/O code and the syscall dominates - so it is not the reason for the change, only a consequence of it. Allocated in retro_vfs_file_open_impl() when path_is_cdrom() matches, zeroed because the paths below rely on the old inline member having been cleared by the handle's calloc() (cue_buf NULL, cur_track 0, last_frame_valid false). Freed in retro_vfs_file_close_impl() at the existing 'end' label, which is reached both by the cdrom goto and by fall-through from the ordinary close path; the NULL test covers the latter. A failed allocation frees the handle and returns NULL, which is safe because nothing has been attached to it at that point - fd is still -1 and orig_path is still NULL. retro_vfs_file_get_cdrom_position() keeps its signature and now returns the pointer rather than the address of the member. It can return NULL for a non-cdrom handle where it previously returned a zeroed one; it has no callers outside this file today, and every existing consumer of the cdrom state gates on scheme == VFS_SCHEME_CDROM before reaching for it. cdrom_cuesheet_overflow_test.c constructs a handle on the stack, so it now supplies its own vfs_cdrom_t and points the handle at it. Verified by building the three HAVE_CDROM translation units clean and running that regression test under ASan: all five cases pass, no leak reported at exit.
This commit is contained in:
1 parent
fdf9a3a21d
commit
ecfa53255b
5 files changed
+163
-128
No files matched your search
@@ -338,7 +338,7 @@ static int cdrom_send_command_win32(const libretro_vfs_implementation_file *stre
|
||||
if (cmd[0] == 0xB9)
|
||||
{
|
||||
double time_taken = (double)(((clock() - t) * 1000) / CLOCKS_PER_SEC);
|
||||
printf("time taken %f ms for DT received length %ld of %" PRId64 " for %02d:%02d:%02d to %02d:%02d:%02d%s req %d cur %d cur_lba %d\n", time_taken, sptd.s.DataTransferLength, len, cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], extra, lba_req, lba_cur, stream->cdrom.cur_lba);
|
||||
printf("time taken %f ms for DT received length %ld of %" PRId64 " for %02d:%02d:%02d to %02d:%02d:%02d%s req %d cur %d cur_lba %d\n", time_taken, sptd.s.DataTransferLength, len, cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], extra, lba_req, lba_cur, stream->cdrom->cur_lba);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
@@ -816,7 +816,7 @@ static int cdrom_send_command(libretro_vfs_implementation_file *stream, CDROM_CM
|
||||
|
||||
lba_req = cdrom_msf_to_lba(cmd[3], cmd[4], cmd[5]);
|
||||
|
||||
if (stream->cdrom.last_frame_valid && lba_req == stream->cdrom.last_frame_lba)
|
||||
if (stream->cdrom->last_frame_valid && lba_req == stream->cdrom->last_frame_lba)
|
||||
{
|
||||
/* use cached frame */
|
||||
cached_read = true;
|
||||
@@ -825,7 +825,7 @@ static int cdrom_send_command(libretro_vfs_implementation_file *stream, CDROM_CM
|
||||
fflush(stdout);
|
||||
#endif
|
||||
/* assumes request_len is always equal to the size of last_frame */
|
||||
memcpy(xfer_buf_pos, stream->cdrom.last_frame, sizeof(stream->cdrom.last_frame));
|
||||
memcpy(xfer_buf_pos, stream->cdrom->last_frame, sizeof(stream->cdrom->last_frame));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -876,13 +876,13 @@ retry:
|
||||
unsigned frame_end = cdrom_msf_to_lba(cmd[6], cmd[7], cmd[8]);
|
||||
|
||||
/* cache the last received frame */
|
||||
memcpy(stream->cdrom.last_frame, xfer_buf_pos, sizeof(stream->cdrom.last_frame));
|
||||
stream->cdrom.last_frame_valid = true;
|
||||
memcpy(stream->cdrom->last_frame, xfer_buf_pos, sizeof(stream->cdrom->last_frame));
|
||||
stream->cdrom->last_frame_valid = true;
|
||||
/* the ending frame is never actually read, so what we really just read is the one right before that */
|
||||
stream->cdrom.last_frame_lba = frame_end - 1;
|
||||
stream->cdrom->last_frame_lba = frame_end - 1;
|
||||
}
|
||||
else
|
||||
stream->cdrom.last_frame_valid = false;
|
||||
stream->cdrom->last_frame_valid = false;
|
||||
|
||||
#if 0
|
||||
printf("Frame %d, adding %" PRId64 " to buf_pos, is now %" PRId64 ". skip is %" PRId64 "\n", i, request_len, (xfer_buf_pos + request_len) - xfer_buf, skip);
|
||||
@@ -1581,7 +1581,7 @@ int cdrom_read(libretro_vfs_implementation_file *stream,
|
||||
|
||||
if (rv)
|
||||
{
|
||||
stream->cdrom.last_frame_valid = false;
|
||||
stream->cdrom->last_frame_valid = false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,9 +72,6 @@ struct retro_vfs_file_handle
|
||||
struct libretro_vfs_implementation_file
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_CDROM
|
||||
vfs_cdrom_t cdrom; /* int64_t alignment */
|
||||
#endif
|
||||
int64_t size;
|
||||
uint64_t mappos;
|
||||
uint64_t mapsize;
|
||||
@@ -88,6 +85,20 @@ struct libretro_vfs_implementation_file
|
||||
int fd;
|
||||
unsigned hints;
|
||||
enum vfs_scheme scheme;
|
||||
#ifdef HAVE_CDROM
|
||||
/* Allocated by retro_vfs_file_open_impl() only when the path
|
||||
* carries the cdrom:// scheme, and freed by
|
||||
* retro_vfs_file_close_impl(). It used to be an inline member at
|
||||
* the head of this struct, which is a poor trade: vfs_cdrom_t
|
||||
* embeds a 2352-byte sector cache, so every open file handle in a
|
||||
* build with HAVE_CDROM cost 2464 bytes instead of 72, and the
|
||||
* fields the read/seek paths actually touch (mappos, mapsize,
|
||||
* mapped, hints) were pushed past offset 2392 and split across two
|
||||
* cache lines instead of sharing one. Every consumer already gates
|
||||
* on 'scheme == VFS_SCHEME_CDROM' before reaching for it, so a
|
||||
* NULL here is unreachable on those paths. */
|
||||
vfs_cdrom_t *cdrom;
|
||||
#endif
|
||||
#ifdef HAVE_SMBCLIENT
|
||||
intptr_t smb_fh;
|
||||
intptr_t smb_ctx;
|
||||
|
||||
@@ -50,21 +50,28 @@ static int failures = 0;
|
||||
static void test_cuesheet_byte_pos_wrap(void)
|
||||
{
|
||||
libretro_vfs_implementation_file stream;
|
||||
/* vfs_cdrom_t hangs off the handle by pointer rather than being an
|
||||
* inline member, so the test supplies its own storage. Backing it
|
||||
* with a local keeps the zero-init below covering both objects and
|
||||
* spares the test an allocation it would have to unwind. */
|
||||
vfs_cdrom_t cdrom_state;
|
||||
char out[64];
|
||||
int64_t rc;
|
||||
const char *fake_cue = "FILE \"track01.bin\" BINARY\nTRACK 01 MODE1/2048\n";
|
||||
size_t cue_size = strlen(fake_cue) + 1; /* incl NUL */
|
||||
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
memset(&cdrom_state, 0, sizeof(cdrom_state));
|
||||
stream.cdrom = &cdrom_state;
|
||||
|
||||
stream.cdrom.cue_buf = strdup(fake_cue);
|
||||
if (!stream.cdrom.cue_buf)
|
||||
stream.cdrom->cue_buf = strdup(fake_cue);
|
||||
if (!stream.cdrom->cue_buf)
|
||||
{
|
||||
printf("[ERROR] strdup failed\n");
|
||||
failures++;
|
||||
return;
|
||||
}
|
||||
stream.cdrom.cue_len = cue_size;
|
||||
stream.cdrom->cue_len = cue_size;
|
||||
|
||||
/* orig_path must end in ".cue" for the read function to dispatch
|
||||
* into the cuesheet path. The function calls path_get_extension
|
||||
@@ -72,14 +79,14 @@ static void test_cuesheet_byte_pos_wrap(void)
|
||||
stream.orig_path = strdup("test.cue");
|
||||
if (!stream.orig_path)
|
||||
{
|
||||
free(stream.cdrom.cue_buf);
|
||||
free(stream.cdrom->cue_buf);
|
||||
printf("[ERROR] strdup failed (orig_path)\n");
|
||||
failures++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Baseline: read at byte_pos=0 with small len should succeed. */
|
||||
stream.cdrom.byte_pos = 0;
|
||||
stream.cdrom->byte_pos = 0;
|
||||
rc = retro_vfs_file_read_cdrom(&stream, out, 10);
|
||||
if (rc < 0 || rc > 10)
|
||||
{
|
||||
@@ -94,7 +101,7 @@ static void test_cuesheet_byte_pos_wrap(void)
|
||||
* cue_len - byte_pos - 1 = 0 - 1 = SIZE_MAX (size_t wrap)
|
||||
* len = SIZE_MAX, memcpy reads gigabytes -> OOB.
|
||||
* Post-patch: byte_pos >= cue_len, return 0. */
|
||||
stream.cdrom.byte_pos = (int64_t)cue_size;
|
||||
stream.cdrom->byte_pos = (int64_t)cue_size;
|
||||
rc = retro_vfs_file_read_cdrom(&stream, out, 10);
|
||||
if (rc != 0)
|
||||
{
|
||||
@@ -106,7 +113,7 @@ static void test_cuesheet_byte_pos_wrap(void)
|
||||
printf("[SUCCESS] byte_pos==cue_len returned 0\n");
|
||||
|
||||
/* Attack 2: byte_pos past cue_len. Pre-patch: same size_t wrap. */
|
||||
stream.cdrom.byte_pos = (int64_t)cue_size + 100;
|
||||
stream.cdrom->byte_pos = (int64_t)cue_size + 100;
|
||||
rc = retro_vfs_file_read_cdrom(&stream, out, 10);
|
||||
if (rc != 0)
|
||||
{
|
||||
@@ -121,7 +128,7 @@ static void test_cuesheet_byte_pos_wrap(void)
|
||||
* SIZE_MAX-ish, then cue_len - huge wraps around into a small
|
||||
* positive value, then memcpy reads gigabytes off cue_buf.
|
||||
* Post-patch: byte_pos < 0, return 0. */
|
||||
stream.cdrom.byte_pos = -1;
|
||||
stream.cdrom->byte_pos = -1;
|
||||
rc = retro_vfs_file_read_cdrom(&stream, out, 10);
|
||||
if (rc != 0)
|
||||
{
|
||||
@@ -139,7 +146,7 @@ static void test_cuesheet_byte_pos_wrap(void)
|
||||
* and the full UINT64_MAX reaches memcpy. OOB.
|
||||
* Post-patch: clamp is unsigned, len is compared to unsigned
|
||||
* remaining, clamp always fires correctly. */
|
||||
stream.cdrom.byte_pos = 5;
|
||||
stream.cdrom->byte_pos = 5;
|
||||
rc = retro_vfs_file_read_cdrom(&stream, out, (uint64_t)-1);
|
||||
{
|
||||
int64_t max_expected = (int64_t)cue_size - 5 - 1;
|
||||
@@ -153,7 +160,7 @@ static void test_cuesheet_byte_pos_wrap(void)
|
||||
printf("[SUCCESS] huge len clamped to rc=%lld\n", (long long)rc);
|
||||
}
|
||||
|
||||
free(stream.cdrom.cue_buf);
|
||||
free(stream.cdrom->cue_buf);
|
||||
free(stream.orig_path);
|
||||
}
|
||||
|
||||
|
||||
@@ -377,6 +377,16 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
||||
#ifdef HAVE_CDROM
|
||||
if (path_is_cdrom(path))
|
||||
{
|
||||
/* The sector cache and cue sheet state only exist for cdrom://
|
||||
* handles, so they are allocated here rather than carried by
|
||||
* every open file. Zeroed, because the old inline member was
|
||||
* zeroed by the calloc() above and the cdrom paths rely on
|
||||
* that (cue_buf NULL, last_frame_valid false, cur_track 0). */
|
||||
if (!(stream->cdrom = (vfs_cdrom_t*)calloc(1, sizeof(*stream->cdrom))))
|
||||
{
|
||||
free(stream);
|
||||
return NULL;
|
||||
}
|
||||
path += sizeof("cdrom://")-1;
|
||||
stream->scheme = VFS_SCHEME_CDROM;
|
||||
}
|
||||
@@ -709,8 +719,15 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream)
|
||||
close(stream->fd);
|
||||
#ifdef HAVE_CDROM
|
||||
end:
|
||||
if (stream->cdrom.cue_buf)
|
||||
free(stream->cdrom.cue_buf);
|
||||
/* Reached both by the goto above and by fall-through from the
|
||||
* non-cdrom path, where stream->cdrom is NULL. */
|
||||
if (stream->cdrom)
|
||||
{
|
||||
if (stream->cdrom->cue_buf)
|
||||
free(stream->cdrom->cue_buf);
|
||||
free(stream->cdrom);
|
||||
stream->cdrom = NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_SMBCLIENT
|
||||
smbend:
|
||||
|
||||
@@ -60,20 +60,20 @@ int64_t retro_vfs_file_seek_cdrom(
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
stream->cdrom.byte_pos = offset;
|
||||
stream->cdrom->byte_pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
stream->cdrom.byte_pos += offset;
|
||||
stream->cdrom->byte_pos += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
stream->cdrom.byte_pos = (stream->cdrom.cue_len - 1) + offset;
|
||||
stream->cdrom->byte_pos = (stream->cdrom->cue_len - 1) + offset;
|
||||
break;
|
||||
}
|
||||
#ifdef CDROM_DEBUG
|
||||
printf("[CDROM] Seek: Path %s Offset %" PRIu64 " is now at %" PRIu64 "\n",
|
||||
stream->orig_path,
|
||||
offset,
|
||||
stream->cdrom.byte_pos);
|
||||
stream->cdrom->byte_pos);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
@@ -98,22 +98,22 @@ int64_t retro_vfs_file_seek_cdrom(
|
||||
#ifdef CDROM_DEBUG
|
||||
seek_type = "SEEK_CUR";
|
||||
#endif
|
||||
stream->cdrom.byte_pos += offset;
|
||||
new_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352);
|
||||
stream->cdrom->byte_pos += offset;
|
||||
new_lba = vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba + (stream->cdrom->byte_pos / 2352);
|
||||
cdrom_lba_to_msf(new_lba, &min, &sec, &frame);
|
||||
}
|
||||
break;
|
||||
case SEEK_END:
|
||||
{
|
||||
ssize_t pregap_lba_len = (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].audio
|
||||
ssize_t pregap_lba_len = (vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].audio
|
||||
? 0
|
||||
: (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba_start));
|
||||
ssize_t lba_len = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_size - pregap_lba_len;
|
||||
: (vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba - vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba_start));
|
||||
ssize_t lba_len = vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].track_size - pregap_lba_len;
|
||||
#ifdef CDROM_DEBUG
|
||||
seek_type = "SEEK_END";
|
||||
#endif
|
||||
cdrom_lba_to_msf(lba_len + lba, &min, &sec, &frame);
|
||||
stream->cdrom.byte_pos = lba_len * 2352;
|
||||
stream->cdrom->byte_pos = lba_len * 2352;
|
||||
}
|
||||
break;
|
||||
case SEEK_SET:
|
||||
@@ -122,16 +122,16 @@ int64_t retro_vfs_file_seek_cdrom(
|
||||
#ifdef CDROM_DEBUG
|
||||
seek_type = "SEEK_SET";
|
||||
#endif
|
||||
stream->cdrom.byte_pos = offset;
|
||||
cdrom_lba_to_msf(vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352), &min, &sec, &frame);
|
||||
stream->cdrom->byte_pos = offset;
|
||||
cdrom_lba_to_msf(vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba + (stream->cdrom->byte_pos / 2352), &min, &sec, &frame);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
stream->cdrom.cur_min = min;
|
||||
stream->cdrom.cur_sec = sec;
|
||||
stream->cdrom.cur_frame = frame;
|
||||
stream->cdrom.cur_lba = cdrom_msf_to_lba(min, sec, frame);
|
||||
stream->cdrom->cur_min = min;
|
||||
stream->cdrom->cur_sec = sec;
|
||||
stream->cdrom->cur_frame = frame;
|
||||
stream->cdrom->cur_lba = cdrom_msf_to_lba(min, sec, frame);
|
||||
|
||||
#ifdef CDROM_DEBUG
|
||||
printf(
|
||||
@@ -139,11 +139,11 @@ int64_t retro_vfs_file_seek_cdrom(
|
||||
seek_type,
|
||||
stream->orig_path,
|
||||
offset,
|
||||
stream->cdrom.byte_pos,
|
||||
(unsigned)stream->cdrom.cur_min,
|
||||
(unsigned)stream->cdrom.cur_sec,
|
||||
(unsigned)stream->cdrom.cur_frame,
|
||||
stream->cdrom.cur_lba);
|
||||
stream->cdrom->byte_pos,
|
||||
(unsigned)stream->cdrom->cur_min,
|
||||
(unsigned)stream->cdrom->cur_sec,
|
||||
(unsigned)stream->cdrom->cur_frame,
|
||||
stream->cdrom->cur_lba);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
@@ -162,7 +162,7 @@ void retro_vfs_file_open_cdrom(
|
||||
size_t path_len = strlen(path);
|
||||
const char *ext = path_get_extension(path);
|
||||
|
||||
stream->cdrom.cur_track = 1;
|
||||
stream->cdrom->cur_track = 1;
|
||||
|
||||
if ( !(ext[0] == 'c' && ext[1] == 'u' && ext[2] == 'e' && ext[3] == '\0')
|
||||
&& !(ext[0] == 'b' && ext[1] == 'i' && ext[2] == 'n' && ext[3] == '\0'))
|
||||
@@ -183,9 +183,9 @@ void retro_vfs_file_open_cdrom(
|
||||
* TOC array (OOB read). Leave the init value (1)
|
||||
* in place on reject. */
|
||||
if (parsed >= 1 && parsed <= 99)
|
||||
stream->cdrom.cur_track = parsed;
|
||||
stream->cdrom->cur_track = parsed;
|
||||
#ifdef CDROM_DEBUG
|
||||
printf("[CDROM] Opening track %d\n", stream->cdrom.cur_track);
|
||||
printf("[CDROM] Opening track %d\n", stream->cdrom->cur_track);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
@@ -200,8 +200,8 @@ void retro_vfs_file_open_cdrom(
|
||||
if (path[5] >= '0' && path[5] <= '9')
|
||||
{
|
||||
cdrom_path[7] = path[5];
|
||||
stream->cdrom.drive = path[5];
|
||||
vfs_cdrom_toc.drive = stream->cdrom.drive;
|
||||
stream->cdrom->drive = path[5];
|
||||
vfs_cdrom_toc.drive = stream->cdrom->drive;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,29 +217,29 @@ void retro_vfs_file_open_cdrom(
|
||||
|
||||
if (ext[0] == 'c' && ext[1] == 'u' && ext[2] == 'e' && ext[3] == '\0')
|
||||
{
|
||||
if (stream->cdrom.cue_buf)
|
||||
if (stream->cdrom->cue_buf)
|
||||
{
|
||||
free(stream->cdrom.cue_buf);
|
||||
stream->cdrom.cue_buf = NULL;
|
||||
free(stream->cdrom->cue_buf);
|
||||
stream->cdrom->cue_buf = NULL;
|
||||
}
|
||||
|
||||
cdrom_write_cue(stream,
|
||||
&stream->cdrom.cue_buf,
|
||||
&stream->cdrom.cue_len,
|
||||
stream->cdrom.drive,
|
||||
&stream->cdrom->cue_buf,
|
||||
&stream->cdrom->cue_len,
|
||||
stream->cdrom->drive,
|
||||
&vfs_cdrom_toc.num_tracks,
|
||||
&vfs_cdrom_toc);
|
||||
cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts);
|
||||
|
||||
#ifdef CDROM_DEBUG
|
||||
if (!stream->cdrom.cue_buf || !*stream->cdrom.cue_buf)
|
||||
if (!stream->cdrom->cue_buf || !*stream->cdrom->cue_buf)
|
||||
{
|
||||
printf("[CDROM] Error writing cue sheet.\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[CDROM] CUE Sheet:\n%s\n", stream->cdrom.cue_buf);
|
||||
printf("[CDROM] CUE Sheet:\n%s\n", stream->cdrom->cue_buf);
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
@@ -267,9 +267,9 @@ void retro_vfs_file_open_cdrom(
|
||||
* TOC array (OOB read). Leave the init value (1) in
|
||||
* place on reject. */
|
||||
if (parsed >= 1 && parsed <= 99)
|
||||
stream->cdrom.cur_track = parsed;
|
||||
stream->cdrom->cur_track = parsed;
|
||||
#ifdef CDROM_DEBUG
|
||||
printf("[CDROM] Opening track %d\n", stream->cdrom.cur_track);
|
||||
printf("[CDROM] Opening track %d\n", stream->cdrom->cur_track);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
@@ -283,8 +283,8 @@ void retro_vfs_file_open_cdrom(
|
||||
if ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z'))
|
||||
{
|
||||
cdrom_path[4] = path[0];
|
||||
stream->cdrom.drive = path[0];
|
||||
vfs_cdrom_toc.drive = stream->cdrom.drive;
|
||||
stream->cdrom->drive = path[0];
|
||||
vfs_cdrom_toc.drive = stream->cdrom->drive;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,16 +306,16 @@ void retro_vfs_file_open_cdrom(
|
||||
|
||||
if (ext[0] == 'c' && ext[1] == 'u' && ext[2] == 'e' && ext[3] == '\0')
|
||||
{
|
||||
if (stream->cdrom.cue_buf)
|
||||
if (stream->cdrom->cue_buf)
|
||||
{
|
||||
free(stream->cdrom.cue_buf);
|
||||
stream->cdrom.cue_buf = NULL;
|
||||
free(stream->cdrom->cue_buf);
|
||||
stream->cdrom->cue_buf = NULL;
|
||||
}
|
||||
|
||||
cdrom_write_cue(stream,
|
||||
&stream->cdrom.cue_buf,
|
||||
&stream->cdrom.cue_len,
|
||||
stream->cdrom.drive,
|
||||
&stream->cdrom->cue_buf,
|
||||
&stream->cdrom->cue_len,
|
||||
stream->cdrom->drive,
|
||||
&vfs_cdrom_toc.num_tracks,
|
||||
&vfs_cdrom_toc);
|
||||
cdrom_get_timeouts(stream,
|
||||
@@ -331,7 +331,7 @@ void retro_vfs_file_open_cdrom(
|
||||
int fd = -1;
|
||||
int index = 0;
|
||||
|
||||
stream->cdrom.cur_track = 1;
|
||||
stream->cdrom->cur_track = 1;
|
||||
|
||||
if ( !(ext[0] == 'c' && ext[1] == 'u' && ext[2] == 'e' && ext[3] == '\0')
|
||||
&& !(ext[0] == 'b' && ext[1] == 'i' && ext[2] == 'n' && ext[3] == '\0'))
|
||||
@@ -352,7 +352,7 @@ void retro_vfs_file_open_cdrom(
|
||||
* TOC array (OOB read). Leave the init value (1)
|
||||
* in place on reject. */
|
||||
if (parsed >= 1 && parsed <= 99)
|
||||
stream->cdrom.cur_track = parsed;
|
||||
stream->cdrom->cur_track = parsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -365,8 +365,8 @@ void retro_vfs_file_open_cdrom(
|
||||
if (path[5] >= '0' && path[5] <= '9')
|
||||
{
|
||||
index = path[5] - '0';
|
||||
stream->cdrom.drive = path[5];
|
||||
vfs_cdrom_toc.drive = stream->cdrom.drive;
|
||||
stream->cdrom->drive = path[5];
|
||||
vfs_cdrom_toc.drive = stream->cdrom->drive;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -380,47 +380,47 @@ void retro_vfs_file_open_cdrom(
|
||||
|
||||
if (ext[0] == 'c' && ext[1] == 'u' && ext[2] == 'e' && ext[3] == '\0')
|
||||
{
|
||||
if (stream->cdrom.cue_buf)
|
||||
if (stream->cdrom->cue_buf)
|
||||
{
|
||||
free(stream->cdrom.cue_buf);
|
||||
stream->cdrom.cue_buf = NULL;
|
||||
free(stream->cdrom->cue_buf);
|
||||
stream->cdrom->cue_buf = NULL;
|
||||
}
|
||||
|
||||
cdrom_write_cue(stream,
|
||||
&stream->cdrom.cue_buf,
|
||||
&stream->cdrom.cue_len,
|
||||
stream->cdrom.drive,
|
||||
&stream->cdrom->cue_buf,
|
||||
&stream->cdrom->cue_len,
|
||||
stream->cdrom->drive,
|
||||
&vfs_cdrom_toc.num_tracks,
|
||||
&vfs_cdrom_toc);
|
||||
cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts);
|
||||
|
||||
#ifdef CDROM_DEBUG
|
||||
if (!stream->cdrom.cue_buf || !*stream->cdrom.cue_buf)
|
||||
if (!stream->cdrom->cue_buf || !*stream->cdrom->cue_buf)
|
||||
{
|
||||
printf("[CDROM] Error writing cue sheet.\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[CDROM] CUE Sheet:\n%s\n", stream->cdrom.cue_buf);
|
||||
printf("[CDROM] CUE Sheet:\n%s\n", stream->cdrom->cue_buf);
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if (vfs_cdrom_toc.num_tracks > 1 && stream->cdrom.cur_track)
|
||||
if (vfs_cdrom_toc.num_tracks > 1 && stream->cdrom->cur_track)
|
||||
{
|
||||
stream->cdrom.cur_min = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].min;
|
||||
stream->cdrom.cur_sec = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].sec;
|
||||
stream->cdrom.cur_frame = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].frame;
|
||||
stream->cdrom.cur_lba = cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame);
|
||||
stream->cdrom->cur_min = vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].min;
|
||||
stream->cdrom->cur_sec = vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].sec;
|
||||
stream->cdrom->cur_frame = vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].frame;
|
||||
stream->cdrom->cur_lba = cdrom_msf_to_lba(stream->cdrom->cur_min, stream->cdrom->cur_sec, stream->cdrom->cur_frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
stream->cdrom.cur_min = vfs_cdrom_toc.track[0].min;
|
||||
stream->cdrom.cur_sec = vfs_cdrom_toc.track[0].sec;
|
||||
stream->cdrom.cur_frame = vfs_cdrom_toc.track[0].frame;
|
||||
stream->cdrom.cur_lba = cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame);
|
||||
stream->cdrom->cur_min = vfs_cdrom_toc.track[0].min;
|
||||
stream->cdrom->cur_sec = vfs_cdrom_toc.track[0].sec;
|
||||
stream->cdrom->cur_frame = vfs_cdrom_toc.track[0].frame;
|
||||
stream->cdrom->cur_lba = cdrom_msf_to_lba(stream->cdrom->cur_min, stream->cdrom->cur_sec, stream->cdrom->cur_frame);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,10 +463,10 @@ int64_t retro_vfs_file_tell_cdrom(libretro_vfs_implementation_file *stream)
|
||||
&& ext[3] == '\0')
|
||||
{
|
||||
#ifdef CDROM_DEBUG
|
||||
printf("[CDROM] (cue) Tell: Path %s Position %" PRIu64 "\n", stream->orig_path, stream->cdrom.byte_pos);
|
||||
printf("[CDROM] (cue) Tell: Path %s Position %" PRIu64 "\n", stream->orig_path, stream->cdrom->byte_pos);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
return stream->cdrom.byte_pos;
|
||||
return stream->cdrom->byte_pos;
|
||||
}
|
||||
else if ( (ext[0] == 'b' || ext[0] == 'B')
|
||||
&& (ext[1] == 'i' || ext[1] == 'I')
|
||||
@@ -474,10 +474,10 @@ int64_t retro_vfs_file_tell_cdrom(libretro_vfs_implementation_file *stream)
|
||||
&& ext[3] == '\0')
|
||||
{
|
||||
#ifdef CDROM_DEBUG
|
||||
printf("[CDROM] (bin) Tell: Path %s Position %" PRId64 "\n", stream->orig_path, stream->cdrom.byte_pos);
|
||||
printf("[CDROM] (bin) Tell: Path %s Position %" PRId64 "\n", stream->orig_path, stream->cdrom->byte_pos);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
return stream->cdrom.byte_pos;
|
||||
return stream->cdrom->byte_pos;
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -497,8 +497,8 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
||||
/* Guard against byte_pos being outside the cue buffer (can
|
||||
* happen after a seek -- seek does not clamp). Treat as
|
||||
* end-of-file. */
|
||||
if ( stream->cdrom.byte_pos < 0
|
||||
|| (size_t)stream->cdrom.byte_pos >= stream->cdrom.cue_len)
|
||||
if ( stream->cdrom->byte_pos < 0
|
||||
|| (size_t)stream->cdrom->byte_pos >= stream->cdrom->cue_len)
|
||||
return 0;
|
||||
/* Clamp len against the remaining bytes using unsigned
|
||||
* subtraction. Computing (byte_pos + len) and comparing
|
||||
@@ -507,8 +507,8 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
||||
* one byte before cue_len so consumers that rely on the cue
|
||||
* buffer being NUL-terminated don't re-read the terminator. */
|
||||
{
|
||||
size_t remaining = stream->cdrom.cue_len
|
||||
- (size_t)stream->cdrom.byte_pos;
|
||||
size_t remaining = stream->cdrom->cue_len
|
||||
- (size_t)stream->cdrom->byte_pos;
|
||||
if (remaining > 0)
|
||||
remaining -= 1;
|
||||
if (len > (uint64_t)remaining)
|
||||
@@ -518,11 +518,11 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
||||
printf(
|
||||
"[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 "...\n",
|
||||
len,
|
||||
stream->cdrom.byte_pos);
|
||||
stream->cdrom->byte_pos);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
memcpy(s, stream->cdrom.cue_buf + stream->cdrom.byte_pos, (size_t)len);
|
||||
stream->cdrom.byte_pos += len;
|
||||
memcpy(s, stream->cdrom->cue_buf + stream->cdrom->byte_pos, (size_t)len);
|
||||
stream->cdrom->byte_pos += len;
|
||||
|
||||
return (int64_t)len;
|
||||
}
|
||||
@@ -537,34 +537,34 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
||||
unsigned char rmin = 0;
|
||||
unsigned char rsec = 0;
|
||||
unsigned char rframe = 0;
|
||||
size_t skip = stream->cdrom.byte_pos % 2352;
|
||||
size_t skip = stream->cdrom->byte_pos % 2352;
|
||||
|
||||
/* Guard against cur_track == 0 (would index track[-1]) and
|
||||
* against an out-of-range byte_pos. cur_track can become
|
||||
* 0 via a crafted VFS path like "driveN-track00.bin" unless
|
||||
* the parser rejects it (see retro_vfs_file_open_cdrom). */
|
||||
if (stream->cdrom.cur_track == 0
|
||||
|| stream->cdrom.cur_track > 99)
|
||||
if (stream->cdrom->cur_track == 0
|
||||
|| stream->cdrom->cur_track > 99)
|
||||
return 0;
|
||||
{
|
||||
size_t track_bytes =
|
||||
vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes;
|
||||
if ( stream->cdrom.byte_pos < 0
|
||||
|| (size_t)stream->cdrom.byte_pos >= track_bytes)
|
||||
vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].track_bytes;
|
||||
if ( stream->cdrom->byte_pos < 0
|
||||
|| (size_t)stream->cdrom->byte_pos >= track_bytes)
|
||||
return 0;
|
||||
/* Clamp len against remaining bytes using unsigned
|
||||
* subtraction. Computing (byte_pos + len) first is a
|
||||
* uint64_t wrap hazard when len is attacker-controlled. */
|
||||
{
|
||||
size_t remaining = track_bytes - (size_t)stream->cdrom.byte_pos;
|
||||
size_t remaining = track_bytes - (size_t)stream->cdrom->byte_pos;
|
||||
if (len > (uint64_t)remaining)
|
||||
len = (uint64_t)remaining;
|
||||
}
|
||||
}
|
||||
|
||||
cdrom_lba_to_msf(stream->cdrom.cur_lba, &min, &sec, &frame);
|
||||
cdrom_lba_to_msf(stream->cdrom.cur_lba
|
||||
- vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba,
|
||||
cdrom_lba_to_msf(stream->cdrom->cur_lba, &min, &sec, &frame);
|
||||
cdrom_lba_to_msf(stream->cdrom->cur_lba
|
||||
- vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba,
|
||||
&rmin, &rsec, &rframe);
|
||||
|
||||
#ifdef CDROM_DEBUG
|
||||
@@ -572,14 +572,14 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
||||
"[CDROM] Read: Reading %" PRIu64 " bytes from %s starting at byte offset %" PRIu64 " (rMSF %02u:%02u:%02u aMSF %02u:%02u:%02u) (LBA %u) skip %" PRIu64 "...\n",
|
||||
len,
|
||||
stream->orig_path,
|
||||
stream->cdrom.byte_pos,
|
||||
stream->cdrom->byte_pos,
|
||||
(unsigned)rmin,
|
||||
(unsigned)rsec,
|
||||
(unsigned)rframe,
|
||||
(unsigned)min,
|
||||
(unsigned)sec,
|
||||
(unsigned)frame,
|
||||
stream->cdrom.cur_lba,
|
||||
stream->cdrom->cur_lba,
|
||||
skip);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
@@ -588,7 +588,7 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
||||
rv = cdrom_read(stream, &vfs_cdrom_toc.timeouts, min, sec,
|
||||
frame, s, (size_t)len, skip);
|
||||
#else
|
||||
rv = cdrom_read_lba(stream, stream->cdrom.cur_lba, s,
|
||||
rv = cdrom_read_lba(stream, stream->cdrom->cur_lba, s,
|
||||
(size_t)len, skip);
|
||||
#endif
|
||||
|
||||
@@ -601,28 +601,28 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream->cdrom.byte_pos += len;
|
||||
stream->cdrom.cur_lba =
|
||||
vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba
|
||||
+ (stream->cdrom.byte_pos / 2352);
|
||||
stream->cdrom->byte_pos += len;
|
||||
stream->cdrom->cur_lba =
|
||||
vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba
|
||||
+ (stream->cdrom->byte_pos / 2352);
|
||||
|
||||
cdrom_lba_to_msf(stream->cdrom.cur_lba,
|
||||
&stream->cdrom.cur_min,
|
||||
&stream->cdrom.cur_sec,
|
||||
&stream->cdrom.cur_frame);
|
||||
cdrom_lba_to_msf(stream->cdrom->cur_lba,
|
||||
&stream->cdrom->cur_min,
|
||||
&stream->cdrom->cur_sec,
|
||||
&stream->cdrom->cur_frame);
|
||||
|
||||
#ifdef CDROM_DEBUG
|
||||
printf(
|
||||
"[CDROM] read %" PRIu64 " bytes, position is now: %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)\n",
|
||||
len,
|
||||
stream->cdrom.byte_pos,
|
||||
(unsigned)stream->cdrom.cur_min,
|
||||
(unsigned)stream->cdrom.cur_sec,
|
||||
(unsigned)stream->cdrom.cur_frame,
|
||||
stream->cdrom->byte_pos,
|
||||
(unsigned)stream->cdrom->cur_min,
|
||||
(unsigned)stream->cdrom->cur_sec,
|
||||
(unsigned)stream->cdrom->cur_frame,
|
||||
cdrom_msf_to_lba(
|
||||
stream->cdrom.cur_min,
|
||||
stream->cdrom.cur_sec,
|
||||
stream->cdrom.cur_frame)
|
||||
stream->cdrom->cur_min,
|
||||
stream->cdrom->cur_sec,
|
||||
stream->cdrom->cur_frame)
|
||||
);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
@@ -641,5 +641,5 @@ int retro_vfs_file_error_cdrom(libretro_vfs_implementation_file *stream)
|
||||
const vfs_cdrom_t* retro_vfs_file_get_cdrom_position(
|
||||
const libretro_vfs_implementation_file *stream)
|
||||
{
|
||||
return &stream->cdrom;
|
||||
return stream->cdrom;
|
||||
}
|
||||
Reference in new issue
Block a user