Skip to content

Commit 528f42e

Browse files
Fix memory leaks, and reduce number of reallocs (emscripten-forge#38)
1 parent 387a794 commit 528f42e

File tree

3 files changed

+20
-16
lines changed

3 files changed

+20
-16
lines changed

src/index.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,10 @@ export const initUntarJS = async (): Promise<IUnpackJSAPI> => {
2424
let inputPtr: number | null = wasmModule._malloc(data.length);
2525
wasmModule.HEAPU8.set(data, inputPtr);
2626

27-
// fileCountPtr is the pointer to 4 bytes of memory in WebAssembly's heap that holds fileCount value from the ExtractedArchive structure in unpack.c.
28-
let fileCountPtr: number | null = wasmModule._malloc(4);
2927

3028
let resultPtr: number | null = wasmModule._extract_archive(
3129
inputPtr,
3230
data.length,
33-
fileCountPtr,
3431
decompressionOnly
3532
);
3633
const files: FilesData = {};
@@ -64,10 +61,8 @@ export const initUntarJS = async (): Promise<IUnpackJSAPI> => {
6461
errorMessage
6562
);
6663
wasmModule._free(inputPtr);
67-
wasmModule._free(fileCountPtr);
6864
wasmModule._free_extracted_archive(resultPtr);
6965
inputPtr = null;
70-
fileCountPtr = null;
7166
resultPtr = null;
7267
errorMessagePtr = null;
7368
throw new Error(errorMessage);
@@ -110,10 +105,8 @@ export const initUntarJS = async (): Promise<IUnpackJSAPI> => {
110105
}
111106

112107
wasmModule._free(inputPtr);
113-
wasmModule._free(fileCountPtr);
114108
wasmModule._free_extracted_archive(resultPtr);
115109
inputPtr = null;
116-
fileCountPtr = null;
117110
resultPtr = null;
118111
errorMessagePtr = null;
119112

src/unpack.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ export interface IWasmModule {
88
_extract_archive(
99
inputPtr: number,
1010
inputSize: number,
11-
fileCountPtr: number,
1211
decompressionOnly: boolean
1312
): number;
1413
getValue(ptr: number, type: string): number;

unpack.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ typedef struct {
2121

2222

2323
EMSCRIPTEN_KEEPALIVE
24-
ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize, size_t* fileCount, bool decompressionOnly ) {
24+
ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize, bool decompressionOnly ) {
2525
struct archive* archive;
2626
struct archive_entry* entry;
27+
size_t files_struct_length = 100;
2728
FileData* files = NULL;
2829
size_t files_count = 0;
2930

@@ -50,26 +51,36 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize, size_t*
5051
archive_read_free(archive);
5152
return result;
5253
}
54+
files = malloc(sizeof(FileData) * files_struct_length);
5355

5456
while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
5557
const char* filename = decompressionOnly ? "decompression.json": archive_entry_pathname(entry);
5658
size_t entrySize = decompressionOnly ? inputSize: archive_entry_size(entry);
57-
files= realloc(files, sizeof(FileData) * (files_count + 1));
58-
if (!files) {
59-
archive_read_free(archive);
60-
result->status = 0;
61-
snprintf(result->error_message, sizeof(result->error_message), "Memory allocation error for file data.");
62-
return result;
59+
if (files_count + 1 > files_struct_length) {
60+
files_struct_length *= 2; // double the length
61+
FileData* oldfiles = files;
62+
files= realloc(files, sizeof(FileData) * files_struct_length);
63+
if (!files) {
64+
archive_read_free(archive);
65+
result->status = 0;
66+
result->fileCount = files_count;
67+
result->files = oldfiles; // otherwise memory is lost, alternatively also everything can be freed.
68+
snprintf(result->error_message, sizeof(result->error_message), "Memory allocation error for file data.");
69+
return result;
70+
}
6371
}
6472
files[files_count].filename = strdup(filename);
6573
files[files_count].data = malloc(entrySize);
6674
files[files_count].data_size = entrySize;
6775

6876
if (!files[files_count].data) {
6977
free(files[files_count].filename);
78+
files[files_count].filename = NULL;
7079
archive_read_free(archive);
7180
result->status = 0;
72-
snprintf(result->error_message, sizeof(result->error_message), "Memory allocation error for file data.");
81+
result->fileCount = files_count;
82+
result->files = files; // otherwise memory is lost, alternatively also everything can be freed.
83+
snprintf(result->error_message, sizeof(result->error_message), "Memory allocation error for file contents.");
7384
return result;
7485
}
7586

@@ -82,6 +93,7 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize, size_t*
8293
free(files[i].data);
8394
}
8495
free(files);
96+
result->files = NULL;
8597
result->status = 0;
8698
snprintf(result->error_message, sizeof(result->error_message), "%s", archive_error_string(archive));
8799
archive_read_free(archive);

0 commit comments

Comments
 (0)