-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathextism-dbg.c
149 lines (127 loc) · 3.95 KB
/
extism-dbg.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <assert.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <extism.h>
static uint8_t *read_stdin(size_t *len);
static uint8_t *read_file(const char *filename, size_t *len);
#define BAIL(msg, ...) \
fprintf(stderr, "ERROR " msg "\n", __VA_ARGS__); \
ret = 1; \
goto cleanup;
int main(int argc, char *argv[]) {
if (argc < 3) {
fputs(
"extism-dbg is minimal Extism runtime used to wrap plugins for "
"debugging\n"
"usage: extism-dbg <Manifest or WebAssembly file> <function> [input]\n",
stderr);
return 1;
}
char *errmsg = NULL; // Plugin error message
int ret = 0; // Return value
size_t wasmLength = 0; // Length of WASM data
uint8_t *wasm = read_file(argv[1], &wasmLength); // Alloc wasm
if (wasm == NULL) {
fprintf(stderr, "ERROR Unable to read WebAssembly file or Manifest: %s\n",
argv[1]);
return 1;
}
bool inputFromFile =
false; // Set to true if `data` is read from a file (or stdin)
uint8_t *data = NULL; // Input data
size_t dataLength = 0; // Input data length
// Create plugin
setenv("EXTISM_DEBUG", "1", 0);
ExtismPlugin *plugin = extism_plugin_new(wasm, wasmLength, NULL, 0, true,
&errmsg); // Alloc plugin
free(wasm); // Free wasm
if (errmsg != NULL) {
BAIL("%s", errmsg);
}
if (plugin == NULL) {
BAIL("%s", "unable to create plugin");
}
// Make sure that the specified function exists before reading input
if (!extism_plugin_function_exists(plugin, argv[2])) {
BAIL("Function does not exist in plugin: %s", argv[2]);
}
// If there are 4 arguments then use the final argument as input
if (argc > 3) {
if (argv[3][0] == '@') {
// @input.txt reads from the file input.txt
inputFromFile = true;
data = read_file(argv[3] + 1, &dataLength); // Alloc data
if (data == NULL) {
BAIL("Unable to read file: %s", argv[3]);
}
} else if (strlen(argv[3]) == 1 && argv[3][0] == '-') {
// - reads from stdin
inputFromFile = true;
data = read_stdin(&dataLength);
} else {
// use the argument as-is
data = (uint8_t *)argv[3];
dataLength = strlen(argv[3]);
}
}
// Call the function
uint32_t rc = extism_plugin_call(plugin, argv[2], data, dataLength);
if (rc != 0) {
BAIL("%s", extism_error(plugin));
} else {
// Handle error
const uint8_t *output = extism_plugin_output_data(plugin);
size_t outputLength = extism_plugin_output_length(plugin);
write(STDOUT_FILENO, output, outputLength);
}
cleanup:
// Data should only be freed if it was read from a file (or stdin)
if (data != NULL && inputFromFile) {
free(data); // Free data
}
if (errmsg != NULL) {
extism_plugin_new_error_free(errmsg);
}
extism_plugin_free(plugin); // Free plugin
return ret;
}
static uint8_t *read_stdin(size_t *len) {
size_t size = 4096;
uint8_t *out = malloc(size);
if (out == NULL)
return NULL;
int ch;
size_t index = 0;
while ((ch = getchar()) != EOF) {
if (index >= size) {
size += 1024;
out = realloc(out, size);
assert(out != NULL);
}
out[index++] = ch;
}
*len = index;
return out;
}
static uint8_t *read_file(const char *filename, size_t *len) {
FILE *fp = fopen(filename, "rb");
if (fp == NULL) {
return NULL;
}
fseek(fp, 0, SEEK_END);
size_t length = ftell(fp);
fseek(fp, 0, SEEK_SET);
uint8_t *data = malloc(length);
if (data == NULL) {
fclose(fp);
return NULL;
}
assert(fread(data, 1, length, fp) == length);
fclose(fp);
*len = length;
return data;
}