From 7828d3d6417300d0fa1750310baeb69c0210db27 Mon Sep 17 00:00:00 2001 From: X7123M3-256 Date: Fri, 26 Feb 2016 21:40:19 +0000 Subject: [PATCH 1/7] Automatically fix unexportable objects so they can be exported normally --- src/object.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/src/object.c b/src/object.c index c86dc80c4e..5c1f77415a 100644 --- a/src/object.c +++ b/src/object.c @@ -96,13 +96,14 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi int calculatedChecksum=object_calculate_checksum(&openedEntry, chunk, *chunkSize); // Calculate and check checksum - if (calculatedChecksum != openedEntry.checksum) { + if (calculatedChecksum != openedEntry.checksum&&!gConfigGeneral.allow_loading_with_incorrect_checksum) { char buffer[100]; sprintf(buffer, "Object Load failed due to checksum failure: calculated checksum %d, object says %d.", calculatedChecksum, (int)openedEntry.checksum); log_error(buffer); RCT2_GLOBAL(0x00F42BD9, uint8) = 2; free(chunk); return 0; + } objectType = openedEntry.flags & 0x0F; @@ -208,10 +209,56 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) chunkHeader.encoding = object_entry_group_encoding[type]; chunkHeader.length = installed_entry->chunk_size; + + //Check if content of object file matches the stored checksum. If it does not, then fix it. + int calculated_checksum=object_calculate_checksum(entry,chunk,installed_entry->chunk_size); + if(entry->checksum!=calculated_checksum) + { + printf("Chunk size %d\n",chunkHeader.length); + + printf("Fixing object with invalid checksum\n"); + //Store the current length of the header - it's the offset at which we will write the extra bytes + int salt_offset=chunkHeader.length; + /*Allocate a new chunk 11 bytes longer. + I would just realloc the old one, but realloc can move the data, leaving dangling pointers + into the old buffer. If the chunk is only referenced in one place it would be safe to realloc + it and update that reference, but I don't know the codebase well enough to know if that's the + case, so to be on the safe side I copy it*/ + uint8* new_chunk=malloc(chunkHeader.length+11); + memcpy(new_chunk,chunk,chunkHeader.length); + //It should be safe to update these in-place because they are local + chunk=new_chunk; + chunkHeader.length+=11; + + printf("New chunk size %d\n",chunkHeader.length); + + /*Next work out which bits need to be flipped to make the current checksum match the one in the file + The bitwise rotation compensates for the rotation performed during the checksum calculation*/ + int bits_to_flip=entry->checksum^((calculated_checksum<<25)|(calculated_checksum>>7)); + /*Each set bit encountered during encoding flips one bit of the resulting checksum (so each bit of the checksum is an XOR + of bits from the file). Here, we take each bit that should be flipped in the checksum and set one of the bits in the data + that maps to it. 11 bytes is the minimum needed to touch every bit of the checksum - with less than that, you wouldn't + always be able to make the checksum come out to the desired target*/ + chunk[salt_offset]=(bits_to_flip&0x00000001)<<7;; + chunk[salt_offset+1]=((bits_to_flip&0x00200000)>>14); + chunk[salt_offset+2]=((bits_to_flip&0x000007F8)>>3); + chunk[salt_offset+3]=((bits_to_flip&0xFF000000)>>24); + chunk[salt_offset+4]=((bits_to_flip&0x00100000)>>13); + chunk[salt_offset+5]=(bits_to_flip&0x00000004)>>2; + chunk[salt_offset+6]=0; + chunk[salt_offset+7]=((bits_to_flip&0x000FF000)>>12); + chunk[salt_offset+8]=(bits_to_flip&0x00000002)>>1; + chunk[salt_offset+9]=(bits_to_flip&0x00C00000)>>22; + chunk[salt_offset+10]=(bits_to_flip&0x00000800)>>11; + } + size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry), chunk, chunkHeader); SDL_RWwrite(rw, dst_buffer, 1, size_dst); - free(dst_buffer); + + + + return 1; } @@ -237,9 +284,16 @@ int object_load_packed(SDL_RWops* rw) } if (object_calculate_checksum(&entry, chunk, chunkSize) != entry.checksum){ + if(gConfigGeneral.allow_loading_with_incorrect_checksum) + { + log_warning("Checksum mismatch from packed object: %.8s", entry.name); + } + else + { log_error("Checksum mismatch from packed object: %.8s", entry.name); free(chunk); return 0; + } } int type = entry.flags & 0x0F; From 00365754132f4a3960b4b5238bfe207828cf0228 Mon Sep 17 00:00:00 2001 From: X7123M3-256 Date: Fri, 26 Feb 2016 22:06:30 +0000 Subject: [PATCH 2/7] Fix memory leak in the checksum fixing code --- src/object.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/object.c b/src/object.c index 5c1f77415a..d48359bfba 100644 --- a/src/object.c +++ b/src/object.c @@ -227,7 +227,6 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) uint8* new_chunk=malloc(chunkHeader.length+11); memcpy(new_chunk,chunk,chunkHeader.length); //It should be safe to update these in-place because they are local - chunk=new_chunk; chunkHeader.length+=11; printf("New chunk size %d\n",chunkHeader.length); @@ -239,26 +238,30 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) of bits from the file). Here, we take each bit that should be flipped in the checksum and set one of the bits in the data that maps to it. 11 bytes is the minimum needed to touch every bit of the checksum - with less than that, you wouldn't always be able to make the checksum come out to the desired target*/ - chunk[salt_offset]=(bits_to_flip&0x00000001)<<7;; - chunk[salt_offset+1]=((bits_to_flip&0x00200000)>>14); - chunk[salt_offset+2]=((bits_to_flip&0x000007F8)>>3); - chunk[salt_offset+3]=((bits_to_flip&0xFF000000)>>24); - chunk[salt_offset+4]=((bits_to_flip&0x00100000)>>13); - chunk[salt_offset+5]=(bits_to_flip&0x00000004)>>2; - chunk[salt_offset+6]=0; - chunk[salt_offset+7]=((bits_to_flip&0x000FF000)>>12); - chunk[salt_offset+8]=(bits_to_flip&0x00000002)>>1; - chunk[salt_offset+9]=(bits_to_flip&0x00C00000)>>22; - chunk[salt_offset+10]=(bits_to_flip&0x00000800)>>11; + new_chunk[salt_offset]=(bits_to_flip&0x00000001)<<7;; + new_chunk[salt_offset+1]=((bits_to_flip&0x00200000)>>14); + new_chunk[salt_offset+2]=((bits_to_flip&0x000007F8)>>3); + new_chunk[salt_offset+3]=((bits_to_flip&0xFF000000)>>24); + new_chunk[salt_offset+4]=((bits_to_flip&0x00100000)>>13); + new_chunk[salt_offset+5]=(bits_to_flip&0x00000004)>>2; + new_chunk[salt_offset+6]=0; + new_chunk[salt_offset+7]=((bits_to_flip&0x000FF000)>>12); + new_chunk[salt_offset+8]=(bits_to_flip&0x00000002)>>1; + new_chunk[salt_offset+9]=(bits_to_flip&0x00C00000)>>22; + new_chunk[salt_offset+10]=(bits_to_flip&0x00000800)>>11; + + //Write modified chunk data + size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry),new_chunk,chunkHeader); + free(new_chunk); + } + else + { + //If the checksum matches, write chunk data + size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry), chunk, chunkHeader); } - size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry), chunk, chunkHeader); SDL_RWwrite(rw, dst_buffer, 1, size_dst); free(dst_buffer); - - - - return 1; } From ba4681d624a5c6e159923d8905e27db606e3c8ad Mon Sep 17 00:00:00 2001 From: X7123M3-256 Date: Fri, 26 Feb 2016 22:41:55 +0000 Subject: [PATCH 3/7] Remove degug printfs --- src/object.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/object.c b/src/object.c index d48359bfba..100c934b28 100644 --- a/src/object.c +++ b/src/object.c @@ -214,9 +214,6 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) int calculated_checksum=object_calculate_checksum(entry,chunk,installed_entry->chunk_size); if(entry->checksum!=calculated_checksum) { - printf("Chunk size %d\n",chunkHeader.length); - - printf("Fixing object with invalid checksum\n"); //Store the current length of the header - it's the offset at which we will write the extra bytes int salt_offset=chunkHeader.length; /*Allocate a new chunk 11 bytes longer. @@ -229,8 +226,6 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) //It should be safe to update these in-place because they are local chunkHeader.length+=11; - printf("New chunk size %d\n",chunkHeader.length); - /*Next work out which bits need to be flipped to make the current checksum match the one in the file The bitwise rotation compensates for the rotation performed during the checksum calculation*/ int bits_to_flip=entry->checksum^((calculated_checksum<<25)|(calculated_checksum>>7)); @@ -313,6 +308,7 @@ int object_load_packed(SDL_RWops* rw) return 0; } + int entryGroupIndex = 0; for (; entryGroupIndex < object_entry_group_counts[type]; entryGroupIndex++){ From 08a0cc92729a3cc6f940b8cbeb029d2a53f57b44 Mon Sep 17 00:00:00 2001 From: X7123M3-256 Date: Fri, 26 Feb 2016 22:56:24 +0000 Subject: [PATCH 4/7] Fix indentation --- src/object.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/object.c b/src/object.c index 100c934b28..98d3dda2dd 100644 --- a/src/object.c +++ b/src/object.c @@ -212,8 +212,7 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) //Check if content of object file matches the stored checksum. If it does not, then fix it. int calculated_checksum=object_calculate_checksum(entry,chunk,installed_entry->chunk_size); - if(entry->checksum!=calculated_checksum) - { + if(entry->checksum!=calculated_checksum){ //Store the current length of the header - it's the offset at which we will write the extra bytes int salt_offset=chunkHeader.length; /*Allocate a new chunk 11 bytes longer. @@ -248,12 +247,10 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) //Write modified chunk data size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry),new_chunk,chunkHeader); free(new_chunk); - } - else - { + } else { //If the checksum matches, write chunk data size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry), chunk, chunkHeader); - } + } SDL_RWwrite(rw, dst_buffer, 1, size_dst); free(dst_buffer); @@ -282,15 +279,13 @@ int object_load_packed(SDL_RWops* rw) } if (object_calculate_checksum(&entry, chunk, chunkSize) != entry.checksum){ - if(gConfigGeneral.allow_loading_with_incorrect_checksum) - { - log_warning("Checksum mismatch from packed object: %.8s", entry.name); - } - else - { - log_error("Checksum mismatch from packed object: %.8s", entry.name); - free(chunk); - return 0; + + if(gConfigGeneral.allow_loading_with_incorrect_checksum){ + log_warning("Checksum mismatch from packed object: %.8s", entry.name); + } else { + log_error("Checksum mismatch from packed object: %.8s", entry.name); + free(chunk); + return 0; } } From cacedda7e4efb9506a51f7aa3c5adcca63d1619f Mon Sep 17 00:00:00 2001 From: X7123M3-256 Date: Sat, 27 Feb 2016 12:10:53 +0000 Subject: [PATCH 5/7] Added spaces around operators --- src/object.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/object.c b/src/object.c index 98d3dda2dd..c3af4b77bb 100644 --- a/src/object.c +++ b/src/object.c @@ -96,7 +96,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi int calculatedChecksum=object_calculate_checksum(&openedEntry, chunk, *chunkSize); // Calculate and check checksum - if (calculatedChecksum != openedEntry.checksum&&!gConfigGeneral.allow_loading_with_incorrect_checksum) { + if (calculatedChecksum != openedEntry.checksum && !gConfigGeneral.allow_loading_with_incorrect_checksum) { char buffer[100]; sprintf(buffer, "Object Load failed due to checksum failure: calculated checksum %d, object says %d.", calculatedChecksum, (int)openedEntry.checksum); log_error(buffer); @@ -212,37 +212,37 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) //Check if content of object file matches the stored checksum. If it does not, then fix it. int calculated_checksum=object_calculate_checksum(entry,chunk,installed_entry->chunk_size); - if(entry->checksum!=calculated_checksum){ + if(entry->checksum != calculated_checksum){ //Store the current length of the header - it's the offset at which we will write the extra bytes - int salt_offset=chunkHeader.length; + int salt_offset = chunkHeader.length; /*Allocate a new chunk 11 bytes longer. I would just realloc the old one, but realloc can move the data, leaving dangling pointers into the old buffer. If the chunk is only referenced in one place it would be safe to realloc it and update that reference, but I don't know the codebase well enough to know if that's the case, so to be on the safe side I copy it*/ - uint8* new_chunk=malloc(chunkHeader.length+11); + uint8* new_chunk = malloc(chunkHeader.length + 11); memcpy(new_chunk,chunk,chunkHeader.length); //It should be safe to update these in-place because they are local - chunkHeader.length+=11; + chunkHeader.length += 11; /*Next work out which bits need to be flipped to make the current checksum match the one in the file The bitwise rotation compensates for the rotation performed during the checksum calculation*/ - int bits_to_flip=entry->checksum^((calculated_checksum<<25)|(calculated_checksum>>7)); + int bits_to_flip = entry->checksum ^ ((calculated_checksum << 25) | (calculated_checksum >> 7)); /*Each set bit encountered during encoding flips one bit of the resulting checksum (so each bit of the checksum is an XOR of bits from the file). Here, we take each bit that should be flipped in the checksum and set one of the bits in the data that maps to it. 11 bytes is the minimum needed to touch every bit of the checksum - with less than that, you wouldn't always be able to make the checksum come out to the desired target*/ - new_chunk[salt_offset]=(bits_to_flip&0x00000001)<<7;; - new_chunk[salt_offset+1]=((bits_to_flip&0x00200000)>>14); - new_chunk[salt_offset+2]=((bits_to_flip&0x000007F8)>>3); - new_chunk[salt_offset+3]=((bits_to_flip&0xFF000000)>>24); - new_chunk[salt_offset+4]=((bits_to_flip&0x00100000)>>13); - new_chunk[salt_offset+5]=(bits_to_flip&0x00000004)>>2; - new_chunk[salt_offset+6]=0; - new_chunk[salt_offset+7]=((bits_to_flip&0x000FF000)>>12); - new_chunk[salt_offset+8]=(bits_to_flip&0x00000002)>>1; - new_chunk[salt_offset+9]=(bits_to_flip&0x00C00000)>>22; - new_chunk[salt_offset+10]=(bits_to_flip&0x00000800)>>11; + new_chunk[salt_offset] = (bits_to_flip & 0x00000001) << 7;; + new_chunk[salt_offset + 1] = ((bits_to_flip & 0x00200000) >> 14); + new_chunk[salt_offset + 2] = ((bits_to_flip & 0x000007F8) >> 3); + new_chunk[salt_offset + 3] = ((bits_to_flip & 0xFF000000) >> 24); + new_chunk[salt_offset + 4] = ((bits_to_flip & 0x00100000) >> 13); + new_chunk[salt_offset + 5] = (bits_to_flip & 0x00000004) >> 2; + new_chunk[salt_offset + 6] = 0; + new_chunk[salt_offset + 7] = ((bits_to_flip & 0x000FF000) >> 12); + new_chunk[salt_offset + 8] = (bits_to_flip & 0x00000002) >> 1; + new_chunk[salt_offset + 9] = (bits_to_flip & 0x00C00000) >> 22; + new_chunk[salt_offset + 10] = (bits_to_flip & 0x00000800) >> 11; //Write modified chunk data size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry),new_chunk,chunkHeader); From 93ed052e200a584c672a88db560267fc4a865c2e Mon Sep 17 00:00:00 2001 From: X7123M3-256 Date: Sat, 27 Feb 2016 12:50:03 +0000 Subject: [PATCH 6/7] Added more spaces and removed duplicate semicolon --- src/object.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/object.c b/src/object.c index c3af4b77bb..5431d987f4 100644 --- a/src/object.c +++ b/src/object.c @@ -93,7 +93,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi } SDL_RWclose(rw); - int calculatedChecksum=object_calculate_checksum(&openedEntry, chunk, *chunkSize); + int calculatedChecksum = object_calculate_checksum(&openedEntry, chunk, *chunkSize); // Calculate and check checksum if (calculatedChecksum != openedEntry.checksum && !gConfigGeneral.allow_loading_with_incorrect_checksum) { @@ -211,7 +211,7 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) //Check if content of object file matches the stored checksum. If it does not, then fix it. - int calculated_checksum=object_calculate_checksum(entry,chunk,installed_entry->chunk_size); + int calculated_checksum = object_calculate_checksum(entry, chunk, installed_entry->chunk_size); if(entry->checksum != calculated_checksum){ //Store the current length of the header - it's the offset at which we will write the extra bytes int salt_offset = chunkHeader.length; @@ -221,7 +221,7 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) it and update that reference, but I don't know the codebase well enough to know if that's the case, so to be on the safe side I copy it*/ uint8* new_chunk = malloc(chunkHeader.length + 11); - memcpy(new_chunk,chunk,chunkHeader.length); + memcpy(new_chunk,chunk, chunkHeader.length); //It should be safe to update these in-place because they are local chunkHeader.length += 11; @@ -232,7 +232,7 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) of bits from the file). Here, we take each bit that should be flipped in the checksum and set one of the bits in the data that maps to it. 11 bytes is the minimum needed to touch every bit of the checksum - with less than that, you wouldn't always be able to make the checksum come out to the desired target*/ - new_chunk[salt_offset] = (bits_to_flip & 0x00000001) << 7;; + new_chunk[salt_offset] = (bits_to_flip & 0x00000001) << 7; new_chunk[salt_offset + 1] = ((bits_to_flip & 0x00200000) >> 14); new_chunk[salt_offset + 2] = ((bits_to_flip & 0x000007F8) >> 3); new_chunk[salt_offset + 3] = ((bits_to_flip & 0xFF000000) >> 24); From 9589a98d40c956e6a7607900dd088c12e2e2615e Mon Sep 17 00:00:00 2001 From: X7123M3-256 Date: Sat, 27 Feb 2016 13:13:15 +0000 Subject: [PATCH 7/7] Added even more spaces --- src/object.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/object.c b/src/object.c index 5431d987f4..ea4ea68421 100644 --- a/src/object.c +++ b/src/object.c @@ -212,7 +212,7 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry) //Check if content of object file matches the stored checksum. If it does not, then fix it. int calculated_checksum = object_calculate_checksum(entry, chunk, installed_entry->chunk_size); - if(entry->checksum != calculated_checksum){ + if(entry->checksum != calculated_checksum) { //Store the current length of the header - it's the offset at which we will write the extra bytes int salt_offset = chunkHeader.length; /*Allocate a new chunk 11 bytes longer. @@ -280,7 +280,7 @@ int object_load_packed(SDL_RWops* rw) if (object_calculate_checksum(&entry, chunk, chunkSize) != entry.checksum){ - if(gConfigGeneral.allow_loading_with_incorrect_checksum){ + if(gConfigGeneral.allow_loading_with_incorrect_checksum) { log_warning("Checksum mismatch from packed object: %.8s", entry.name); } else { log_error("Checksum mismatch from packed object: %.8s", entry.name);