Skip to content

Commit 215c3db

Browse files
authored
Merge pull request emscripten-forge#26 from AnastasiaSliusar/add-error-handling
Add error handling
2 parents ccb691b + d112075 commit 215c3db

File tree

3 files changed

+104
-26
lines changed

3 files changed

+104
-26
lines changed

src/index.ts

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,82 @@ export const extractData = async (data: Uint8Array): Promise<IFileData[]> => {
2727
console.error('WASM module not initialized.');
2828
return [];
2929
}
30+
31+
/**Since WebAssembly, memory is accessed using pointers
32+
and the first parameter of extract_archive method from unpack.c, which is Uint8Array of file data, should be a pointer
33+
so we have to allocate memory for file data
34+
**/
3035
const inputPtr = wasmModule._malloc(data.length);
3136
wasmModule.HEAPU8.set(data, inputPtr);
37+
38+
// fileCountPtr is the pointer to 4 bytes of memory in WebAssembly's heap that holds fileCount value from the ExtractedArchive structure in unpack.c.
3239
const fileCountPtr = wasmModule._malloc(4);
33-
const outputSizePtr = wasmModule._malloc(4);
3440

3541
try {
36-
const extractedFilesPtr = wasmModule._extract_archive(
42+
const resultPtr = wasmModule._extract_archive(
3743
inputPtr,
3844
data.length,
39-
outputSizePtr,
4045
fileCountPtr
4146
);
4247

43-
const fileCount = wasmModule.getValue(fileCountPtr, 'i32');
48+
/**
49+
* Since extract_archive returns a pointer that refers to an instance of the ExtractedArchive in unpack.c
50+
typedef struct {
51+
FileData* files;
52+
size_t fileCount;
53+
int status;
54+
char* error_message;
55+
} ExtractedArchive;
56+
57+
its fields are laid out in memory sequentially. Based on this and types each field will take 4 bytes:
58+
59+
4 bytes 4 bytes 4 bytes 4 bytes
60+
---------------|---------------|---------------|---------------
61+
files fileCount status error_message
62+
63+
`resultPtr` points to the beginning of the ExtractedArchive structure in WebAssembly memory
64+
and in order to get pointer of statusPtr we need to calculate it as: 0(offset of file pointer) + 4 (offset of fileCount) + 4 (offset for status)
65+
'status' field and pointer of `error_message` are 32-bit signed integer
66+
*/
67+
const statusPtr = wasmModule.getValue(resultPtr + 8, 'i32');
68+
const errorMessagePtr = wasmModule.getValue(resultPtr + 12, 'i32');
69+
console.log('status', statusPtr);
70+
console.log('errorMessagePtr', errorMessagePtr);
71+
if (statusPtr !== 1) {
72+
const errorMessage = wasmModule.UTF8ToString(errorMessagePtr);
73+
console.error(
74+
'Extraction failed with status:',
75+
statusPtr,
76+
'Error:',
77+
errorMessage
78+
);
79+
return [];
80+
}
81+
const filesPtr = wasmModule.getValue(resultPtr, 'i32');
82+
const fileCount = wasmModule.getValue(resultPtr + 4, 'i32');
83+
4484
const files: IFileData[] = [];
4585

86+
/**
87+
* FilesPtr is a pointer that refers to an instance of the FileData in unpack.c
88+
typedef struct {
89+
char* filename;
90+
uint8_t* data;
91+
size_t data_size;
92+
} FileData;
93+
94+
and its fields are laid out in memory sequentially too so each field take 4 bytes:
95+
96+
4 bytes 4 bytes 4 bytes
97+
---------------|---------------|---------------
98+
filename data data_size
99+
100+
`filesPtr + i * 12` calculates the memory address of the i-th FileData element in the array
101+
where `12` is the size of each FileData structure in memory in bytes: 4 + 4 + 4
102+
*/
103+
46104
for (let i = 0; i < fileCount; i++) {
47-
const fileDataPtr = extractedFilesPtr + i * (3 * 4);
105+
const fileDataPtr = filesPtr + i * 12;
48106
const filenamePtr = wasmModule.getValue(fileDataPtr, 'i32');
49107
const dataSize = wasmModule.getValue(fileDataPtr + 8, 'i32');
50108
const dataPtr = wasmModule.getValue(fileDataPtr + 4, 'i32');
@@ -61,14 +119,15 @@ export const extractData = async (data: Uint8Array): Promise<IFileData[]> => {
61119
});
62120
}
63121

64-
wasmModule._free(fileCountPtr);
65-
wasmModule._free(outputSizePtr);
66122
wasmModule._free(inputPtr);
67-
wasmModule._free(extractedFilesPtr);
123+
wasmModule._free(fileCountPtr);
124+
wasmModule._free(statusPtr);
125+
wasmModule._free(errorMessagePtr);
126+
wasmModule._free(resultPtr);
68127

69128
return files;
70129
} catch (error) {
71-
console.error('Error during extracting:', error);
130+
console.error('Error during extraction:', error);
72131
return [];
73132
}
74133
};

src/unpack.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ export interface IWasmModule {
66
_extract_archive(
77
inputPtr: number,
88
inputSize: number,
9-
outputSizePtr: number,
109
fileCountPtr: number
1110
): number;
1211
getValue(ptr: number, type: string): number;

unpack.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,42 @@ typedef struct {
1111
size_t data_size;
1212
} FileData;
1313

14+
typedef struct {
15+
FileData* files;
16+
size_t fileCount;
17+
int status;
18+
char* error_message;
19+
} ExtractedArchive;
20+
1421
EMSCRIPTEN_KEEPALIVE
15-
FileData* extract_archive(uint8_t* inputData, size_t inputSize, size_t* outputSize, size_t* fileCount) {
22+
ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize, size_t* fileCount) {
1623
struct archive* archive;
1724
struct archive_entry* entry;
1825
FileData* files = NULL;
1926
size_t files_count = 0;
2027

28+
ExtractedArchive* result = (ExtractedArchive*)malloc(sizeof(ExtractedArchive));
29+
if (!result) {
30+
result->status = 0;
31+
result->error_message = strdup("Memory allocation error for ExtractedArchive.");
32+
return NULL;
33+
}
34+
35+
result->files = NULL;
36+
result->fileCount = 0;
37+
result->status = 1;
38+
result->error_message = NULL;
39+
2140
archive = archive_read_new();
2241
archive_read_support_filter_all(archive);
2342
archive_read_support_format_all(archive);
2443

2544
if (archive_read_open_memory(archive, inputData, inputSize) != ARCHIVE_OK) {
26-
fprintf(stderr, "Error opening archive: %s\n", archive_error_string(archive));
2745
archive_read_free(archive);
28-
return NULL;
46+
result->status = 0;
47+
result->error_message = strdup(archive_error_string(archive));
48+
return result;
2949
}
30-
printf("Archive opened successfully.\n");
3150

3251
while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
3352
const char* filename = archive_entry_pathname(entry);
@@ -36,47 +55,48 @@ FileData* extract_archive(uint8_t* inputData, size_t inputSize, size_t* outputSi
3655

3756
files = realloc(files, sizeof(FileData) * (files_count + 1));
3857
if (!files) {
39-
fprintf(stderr, "Memory allocation error for FileData array.\n");
4058
archive_read_free(archive);
41-
return NULL;
59+
result->status = 0;
60+
result->error_message = strdup("Memory allocation error for FileData array.");
61+
return result;
4262
}
4363

4464
files[files_count].filename = strdup(filename);
4565
files[files_count].data = malloc(entrySize);
46-
printf("Setting data_size for file: %s, size: %zu\n", filename, entrySize);
4766
files[files_count].data_size = entrySize;
4867

4968
if (!files[files_count].data) {
50-
fprintf(stderr, "Memory allocation error for file data.\n");
5169
free(files[files_count].filename);
5270
archive_read_free(archive);
53-
return NULL;
71+
result->status = 0;
72+
result->error_message = strdup("Memory allocation error for file data.");
73+
return result;
5474
}
5575

5676
size_t bytesRead = 0;
5777
while (bytesRead < entrySize) {
5878
ssize_t ret = archive_read_data(archive, files[files_count].data + bytesRead, entrySize - bytesRead);
5979
if (ret < 0) {
60-
fprintf(stderr, "Error reading data for %s: %s\n", filename, archive_error_string(archive));
6180
for (size_t i = 0; i <= files_count; i++) {
6281
free(files[i].filename);
6382
free(files[i].data);
6483
}
6584
free(files);
6685
archive_read_free(archive);
67-
return NULL;
86+
result->status = 0;
87+
result->error_message = strdup(archive_error_string(archive));
88+
return result;
6889
}
6990
bytesRead += ret;
70-
printf("Read %zd bytes for file: %s\n", ret, filename);
7191
}
7292
files_count++;
7393
}
7494

7595
archive_read_free(archive);
76-
*outputSize = files_count;
77-
*fileCount = files_count;
78-
79-
return files;
96+
result->files = files;
97+
result->fileCount = files_count;
98+
result->status = 1;
99+
return result;
80100
}
81101

82102

0 commit comments

Comments
 (0)