Skip to content

Commit

Permalink
Merge pull request #34 from mach-kernel/fix-addfile-segfault
Browse files Browse the repository at this point in the history
1.4.5: Fix ADDFILE segfault
  • Loading branch information
mach-kernel authored Dec 17, 2020
2 parents 61b661d + b3e3fcf commit f38d3d5
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 26 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ Any and all contributions are welcome. Included is also a `cadius.pro` file you

## Changelog

#### 1.4.5
- Fix `os_GetFolderFiles` calloc too small.
- AppleSingle check for OOB accesses (thanks [@peterferrie](https://github.com/peterferrie)). [#34](https://github.com/mach-kernel/cadius/pull/34)

#### 1.4.4
- Fix 140KiB volume size assertion (thanks [@inexorabletash](https://github.com/inexorabletash)): [#30](https://github.com/mach-kernel/cadius/pull/27)

Expand Down
39 changes: 24 additions & 15 deletions Src/File_AppleSingle.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ static uint16_t as_field16(uint16_t num)
* @param buf
* @return
*/
bool ASIsAppleSingle(unsigned char *buf)
bool ASIsAppleSingle(unsigned char *buf, size_t buflen)
{
if (buflen < sizeof(AS_MAGIC)) return false;
int buf_magic;
memcpy(&buf_magic, buf, sizeof(AS_MAGIC));
buf_magic = as_field32(buf_magic);
Expand All @@ -35,9 +36,11 @@ bool ASIsAppleSingle(unsigned char *buf)
* @param buf The buffer
* @return
*/
struct as_file_header *ASParseHeader(unsigned char *buf)
struct as_file_header *ASParseHeader(unsigned char *buf, size_t buflen)
{
if (buflen < sizeof(as_file_header)) return NULL;
struct as_file_header *header = malloc(sizeof(as_file_header));
if (!header) return NULL;
struct as_file_header *buf_header = (as_file_header *) buf;

header->magic = as_field32(buf_header->magic);
Expand All @@ -52,9 +55,11 @@ struct as_file_header *ASParseHeader(unsigned char *buf)
* @param entry_buf The entry buffer
* @return
*/
struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf)
struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf, size_t buflen)
{
if (buflen < sizeof(as_prodos_info)) return NULL;
struct as_prodos_info *prodos_entry = malloc(sizeof(as_prodos_info));
if (!prodos_entry) return NULL;
struct as_prodos_info *buf_prodos_entry = (as_prodos_info *) entry_buf;

prodos_entry->access = as_field16(buf_prodos_entry->access);
Expand All @@ -70,19 +75,20 @@ struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf)
* @param buf
* @return
*/
struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char *buf)
struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char *buf, size_t buflen)
{
if (!header)
{
logf_error(" Error: Invalid AppleSingle file!\n");
return NULL;
}

struct as_file_entry *entries = malloc(
header->num_entries * sizeof(as_file_entry)
);
size_t entries_length = header->num_entries * sizeof(as_file_entry);
if (buflen < sizeof(as_file_header) + entries_length) return NULL;

struct as_file_entry *entries = malloc(entries_length);
struct as_file_entry *buf_entries = (as_file_entry *) (buf + sizeof(as_file_header));

memcpy(entries, buf_entries, header->num_entries * sizeof(as_file_entry));

if (IS_LITTLE_ENDIAN)
Expand All @@ -103,9 +109,10 @@ struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char
* @param data The data
* @param data_fork_entry The data fork entry
*/
void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, as_file_entry *data_fork_entry)
void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, size_t datalen, as_file_entry *data_fork_entry)
{
if (data_fork_entry->entry_id != data_fork) return;
if (datalen < data_fork_entry->offset + data_fork_entry->length) return;

unsigned char *data_entry = malloc(data_fork_entry->length);
memcpy(data_entry, data + data_fork_entry->offset, data_fork_entry->length);
Expand All @@ -123,12 +130,14 @@ void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, a
* @param data The data
* @param prodos_entry The prodos entry
*/
void ASDecorateProdosFileInfo(struct prodos_file *current_file, unsigned char *data, as_file_entry *prodos_entry)
void ASDecorateProdosFileInfo(struct prodos_file *current_file, unsigned char *data, size_t datalen, as_file_entry *prodos_entry)
{
if (prodos_entry->entry_id != prodos_file_info) return;
if (datalen < prodos_entry->offset + prodos_entry->length) return;

struct as_prodos_info *info_meta = ASParseProdosEntry(
data + prodos_entry->offset
data + prodos_entry->offset,
prodos_entry->length
);

if (!info_meta) return;
Expand All @@ -147,19 +156,19 @@ void ASDecorateProdosFileInfo(struct prodos_file *current_file, unsigned char *d
* @param current_file
* @param data
*/
void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data)
void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data, size_t datalen)
{
struct as_file_header *header = ASParseHeader(data);
struct as_file_entry *entries = ASGetEntries(header, data);
struct as_file_header *header = ASParseHeader(data, datalen);
struct as_file_entry *entries = ASGetEntries(header, data, datalen);

for (int i = 0; i < header->num_entries; ++i)
switch(entries[i].entry_id)
{
case data_fork:
ASDecorateDataFork(current_file, data, &entries[i]);
ASDecorateDataFork(current_file, data, datalen, &entries[i]);
break;
case prodos_file_info:
ASDecorateProdosFileInfo(current_file, data, &entries[i]);
ASDecorateProdosFileInfo(current_file, data, datalen, &entries[i]);
break;
default:
logf_info(" Entry ID %d unsupported, ignoring!\n", entries[i].entry_id);
Expand Down
14 changes: 7 additions & 7 deletions Src/File_AppleSingle.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@ typedef struct as_from_prodos

#pragma pack(pop)

bool ASIsAppleSingle(unsigned char *buf);
bool ASIsAppleSingle(unsigned char *buf, size_t buflen);

struct as_file_header *ASParseHeader(unsigned char *buf);
struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf);
struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char *buf);
struct as_file_header *ASParseHeader(unsigned char *buf, size_t buflen);
struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf, size_t buflen);
struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char *buf, size_t buflen);

void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, as_file_entry *data_fork_entry);
void ASDeocrateProdosFileInfo(struct prodos_file *current_file, unsigned char *data, as_file_entry *prodos_entry);
void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data);
void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, size_t datalen, as_file_entry *data_fork_entry);
void ASDeocrateProdosFileInfo(struct prodos_file *current_file, unsigned char *data, size_t datalen, as_file_entry *prodos_entry);
void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data, size_t datalen);

struct as_from_prodos ASFromProdosFile(struct prodos_file *file);
2 changes: 1 addition & 1 deletion Src/Main.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ int main(int argc, char *argv[])
struct file_descriptive_entry *folder_entry;

/* Message Information */
logf("%s v 1.4.4 (c) Brutal Deluxe 2011-2013.\n",argv[0]);
logf("%s v 1.4.5 (c) Brutal Deluxe 2011-2013.\n",argv[0]);

/* Vérification des paramètres */
if(argc < 3)
Expand Down
4 changes: 2 additions & 2 deletions Src/Prodos_Add.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,12 +364,12 @@ static struct prodos_file *LoadFile(char *file_path_data, bool zero_case_bits)
return NULL;
}

bool is_apple_single = ASIsAppleSingle(data);
bool is_apple_single = ASIsAppleSingle(data, &current_file->data_length);

if (is_apple_single)
{
logf_info(" AppleSingle format detected!\n");
ASDecorateProdosFile(current_file, data);
ASDecorateProdosFile(current_file, data, &current_file->data_length);
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion Src/os/posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ int os_GetFolderFiles(char *folder_path, char *hierarchy)
if (entry == NULL) break;

// +2 for \0 and a possible slash
char *heap_path = calloc(1, strlen(folder_path) + 2);
char *heap_path = calloc(1, strlen(folder_path) + strlen(entry->d_name) + 2);
strcpy(heap_path, folder_path);

// If there's no trailing dir slash, we append it
Expand Down

0 comments on commit f38d3d5

Please sign in to comment.