From 21cc80f48a07f2a4386c68818f002cba180bbd56 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Tue, 1 Sep 2026 14:52:45 +0100 Subject: [PATCH] Bounds-check CD prefix/suffix arena reads and fix legacy over-reads A DDT2 entry whose slot index points past the stored prefix/suffix block (e.g. a resume-damaged or corrupt image) caused an out-of-bounds heap read that was silently returned as sector data. Validate the pointer and index against the arena length before copying, returning AARUF_ERROR_CANNOT_READ_BLOCK with an Errored status instead. Also clamp the two legacy Mode 2 fallback copies to the actual bare-sector length. --- src/read.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/read.c b/src/read.c index 976bef5..d210874 100644 --- a/src/read.c +++ b/src/read.c @@ -1813,6 +1813,15 @@ AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, const uint64 } else if(prefix_status == SectorStatusNotDumped) res = AARUF_STATUS_SECTOR_NOT_DUMPED; + else if(ctx->sector_prefix == NULL || (prefix_index + 1) * 16 > ctx->sector_prefix_length) + { + FATAL("Sector prefix index %" PRIu64 " outside stored prefix block", prefix_index); + free(bare_data); + *sector_status = SectorStatusErrored; + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_CANNOT_READ_BLOCK"); + return AARUF_ERROR_CANNOT_READ_BLOCK; + } else memcpy(data, ctx->sector_prefix + prefix_index * 16, 16); } @@ -1860,6 +1869,15 @@ AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, const uint64 } else if(suffix_status == SectorStatusNotDumped) res = AARUF_STATUS_SECTOR_NOT_DUMPED; + else if(ctx->sector_suffix == NULL || (suffix_index + 1) * 288 > ctx->sector_suffix_length) + { + FATAL("Sector suffix index %" PRIu64 " outside stored suffix block", suffix_index); + free(bare_data); + *sector_status = SectorStatusErrored; + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_CANNOT_READ_BLOCK"); + return AARUF_ERROR_CANNOT_READ_BLOCK; + } else memcpy(data + 2064, ctx->sector_suffix + suffix_index * 288, 288); } @@ -1906,6 +1924,15 @@ AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, const uint64 } else if(prefix_status == SectorStatusNotDumped) res = AARUF_STATUS_SECTOR_NOT_DUMPED; + else if(ctx->sector_prefix == NULL || (prefix_index + 1) * 16 > ctx->sector_prefix_length) + { + FATAL("Sector prefix index %" PRIu64 " outside stored prefix block", prefix_index); + free(bare_data); + *sector_status = SectorStatusErrored; + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_CANNOT_READ_BLOCK"); + return AARUF_ERROR_CANNOT_READ_BLOCK; + } else memcpy(data, ctx->sector_prefix + prefix_index * 16, 16); } @@ -1963,6 +1990,15 @@ AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, const uint64 } else if(suffix_status == SectorStatusNotDumped) res = AARUF_STATUS_SECTOR_NOT_DUMPED; + else if(ctx->sector_suffix == NULL || (suffix_index + 1) * 288 > ctx->sector_suffix_length) + { + FATAL("Sector suffix index %" PRIu64 " outside stored suffix block", suffix_index); + free(bare_data); + *sector_status = SectorStatusErrored; + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_CANNOT_READ_BLOCK"); + return AARUF_ERROR_CANNOT_READ_BLOCK; + } else { // Mode 2 where ECC/EDC failed — restore user data + stored suffix. @@ -2022,10 +2058,10 @@ AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, const uint64 else if(ctx->mode2_subheaders != NULL) { memcpy(data + 16, ctx->mode2_subheaders + corrected_sector_address * 8, 8); - memcpy(data + 24, bare_data, 2328); + memcpy(data + 24, bare_data, bare_length < 2328 ? bare_length : 2328); } else - memcpy(data + 16, bare_data, 2336); + memcpy(data + 16, bare_data, bare_length < 2336 ? bare_length : 2336); *length = 2352; free(bare_data);