Rizin
unix-like reverse engineering framework and cli tools
run.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2020 thestr4ng3r <info@florianmaerkl.de>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "rz_test.h"
5 #include <rz_cons.h>
6 
7 #if __WINDOWS__
8 static ut8 *crlf2lf(ut8 *str) {
9  char *src = (char *)str;
10  char *dest = src;
11  while (*src) {
12  *dest = *src;
13  if (src[0] == '\r' && src[1] == '\n') {
14  // dest does not move
15  } else {
16  dest++;
17  }
18  src++;
19  }
20  *dest = '\0';
21  return str;
22 }
23 #else
24 #define crlf2lf(x) (x)
25 #endif
26 
27 static RzSubprocessOutput *subprocess_runner(const char *file, const char *args[], size_t args_size,
28  const char *envvars[], const char *envvals[], size_t env_size, ut64 timeout_ms, void *user) {
29  RzSubprocess *proc = rz_subprocess_start(file, args, args_size, envvars, envvals, env_size);
30  if (!proc) {
31  return NULL;
32  }
34  if (r == RZ_SUBPROCESS_TIMEDOUT) {
36  }
38  if (out) {
39  out->timeout = r == RZ_SUBPROCESS_TIMEDOUT;
40  out->out = crlf2lf(out->out);
41  out->err = crlf2lf(out->err);
42  }
44  return out;
45 }
46 
47 #if __WINDOWS__
48 static char *convert_win_cmds(const char *cmds) {
49  char *r = malloc(strlen(cmds) + 1);
50  if (!r) {
51  return NULL;
52  }
53  char *p = r;
54  while (*cmds) {
55  if (*cmds == '!' || (*cmds == '\"' && cmds[1] == '!')) {
56  // Adjust shell syntax for Windows,
57  // only for lines starting with ! or "!
58  char c;
59  for (; c = *cmds, c; cmds++) {
60  if (c == '\\') {
61  // replace \$ by $
62  c = *++cmds;
63  if (c == '$') {
64  *p++ = '$';
65  } else {
66  *p++ = '\\';
67  *p++ = c;
68  }
69  } else if (c == '$') {
70  // replace ${VARNAME} by %VARNAME%
71  c = *++cmds;
72  if (c == '{') {
73  *p++ = '%';
74  cmds++;
75  for (; c = *cmds, c && c != '}'; cmds++) {
76  *p++ = c;
77  }
78  if (c) { // must check c to prevent overflow
79  *p++ = '%';
80  }
81  } else {
82  *p++ = '$';
83  *p++ = c;
84  }
85  } else {
86  *p++ = c;
87  if (c == '\n') {
88  cmds++;
89  break;
90  }
91  }
92  }
93  continue;
94  }
95 
96  // Nothing to do, just copy the line
97  char *lend = strchr(cmds, '\n');
98  size_t llen;
99  if (lend) {
100  llen = lend - cmds + 1;
101  } else {
102  llen = strlen(cmds);
103  }
104  memcpy(p, cmds, llen);
105  cmds += llen;
106  p += llen;
107  }
108  *p = '\0';
109  return rz_str_replace(r, "/dev/null", "nul", true);
110 }
111 #endif
112 
113 static RzSubprocessOutput *run_rz_test(RzTestRunConfig *config, ut64 timeout_ms, const char *cmds, RzList *files, RzList *extra_args, bool load_plugins, RzTestCmdRunner runner, void *user) {
114  RzPVector args;
116  rz_pvector_push(&args, "-escr.utf8=0");
117  rz_pvector_push(&args, "-escr.color=0");
118  rz_pvector_push(&args, "-escr.interactive=0");
119  rz_pvector_push(&args, "-N");
120  RzListIter *it;
121  void *extra_arg, *file_arg;
122  rz_list_foreach (extra_args, it, extra_arg) {
123  rz_pvector_push(&args, extra_arg);
124  }
125  rz_pvector_push(&args, "-Qc");
126 #if __WINDOWS__
127  char *wcmds = convert_win_cmds(cmds);
128  rz_pvector_push(&args, wcmds);
129 #else
130  rz_pvector_push(&args, (void *)cmds);
131 #endif
132  rz_list_foreach (files, it, file_arg) {
133  rz_pvector_push(&args, file_arg);
134  }
135 
136  const char *envvars[] = {
137 #if __WINDOWS__
138  "ANSICON",
139 #endif
140  "RZ_NOPLUGINS"
141  };
142  const char *envvals[] = {
143 #if __WINDOWS__
144  "1",
145 #endif
146  "1"
147  };
148 #if __WINDOWS__
149  size_t env_size = load_plugins ? 1 : 2;
150 #else
151  size_t env_size = load_plugins ? 0 : 1;
152 #endif
153  RzSubprocessOutput *out = runner(config->rz_cmd, args.v.a, rz_pvector_len(&args), envvars, envvals, env_size, timeout_ms, user);
155 #if __WINDOWS__
156  free(wcmds);
157 #endif
158  return out;
159 }
160 
162  RzList *extra_args = test->args.value ? rz_str_split_duplist(test->args.value, " ", true) : NULL;
163  RzList *files = test->file.value ? rz_str_split_duplist(test->file.value, "\n", true) : NULL;
164  RzListIter *it;
165  RzListIter *tmpit;
166  char *token;
167  rz_list_foreach_safe (extra_args, it, tmpit, token) {
168  if (!*token) {
169  rz_list_delete(extra_args, it);
170  }
171  }
172  rz_list_foreach_safe (files, it, tmpit, token) {
173  if (!*token) {
174  rz_list_delete(files, it);
175  }
176  }
177  if (rz_list_empty(files)) {
178  if (!files) {
179  files = rz_list_new();
180  } else {
181  files->free = NULL;
182  }
183  rz_list_push(files, "=");
184  }
185  ut64 timeout_ms = test->timeout.set ? test->timeout.value * 1000 : config->timeout_ms;
186  RzSubprocessOutput *out = run_rz_test(config, timeout_ms, test->cmds.value, files, extra_args, test->load_plugins, runner, user);
187  rz_list_free(extra_args);
189  return out;
190 }
191 
192 RZ_API bool rz_test_cmp_cmd_output(const char *output, const char *expect, const char *regexp) {
193  if (regexp) {
194  RzList *matches = rz_regex_get_match_list(regexp, "e", output);
195  const char *match = rz_list_to_str(matches, '\0');
196  bool equal = (0 == strcmp(expect, match));
197  rz_list_free(matches);
198  RZ_FREE(match);
199  return equal;
200  }
201  return (0 == strcmp(expect, output));
202 }
203 
205  if (!out || out->ret != 0 || !out->out || !out->err || out->timeout) {
206  return false;
207  }
208  const char *expect_out = test->expect.value;
209  const char *regexp_out = test->regexp_out.value;
210  if (expect_out && !rz_test_cmp_cmd_output((char *)out->out, expect_out, regexp_out)) {
211  return false;
212  }
213  const char *expect_err = test->expect_err.value;
214  const char *regexp_err = test->regexp_err.value;
215  if (expect_err && !rz_test_cmp_cmd_output((char *)out->err, expect_err, regexp_err)) {
216  return false;
217  }
218  return true;
219 }
220 
221 #define JQ_CMD "jq"
222 
224  const char *args[] = { "." };
225  const char *invalid_json = "this is not json lol";
227  if (proc) {
228  rz_subprocess_stdin_write(proc, (const ut8 *)invalid_json, strlen(invalid_json));
230  }
231  bool invalid_detected = proc && rz_subprocess_ret(proc) != 0;
233 
234  const char *valid_json = "{\"this is\":\"valid json\",\"lol\":true}";
236  if (proc) {
237  rz_subprocess_stdin_write(proc, (const ut8 *)valid_json, strlen(valid_json));
239  }
240  bool valid_detected = proc && rz_subprocess_ret(proc) == 0;
242 
243  return invalid_detected && valid_detected;
244 }
245 
247  RzList *files = rz_list_new();
248  rz_list_push(files, (void *)config->json_test_file);
249  RzSubprocessOutput *ret = run_rz_test(config, config->timeout_ms, test->cmd, files, NULL, test->load_plugins, runner, user);
251  return ret;
252 }
253 
255  if (!out || out->ret != 0 || !out->out || !out->err || out->timeout) {
256  return false;
257  }
258  const char *args[] = { "." };
260  rz_subprocess_stdin_write(proc, (const ut8 *)out->out, strlen((char *)out->out));
262  bool ret = rz_subprocess_ret(proc) == 0;
264  return ret;
265 }
266 
269  if (!out) {
270  return NULL;
271  }
272 
273  RzPVector args;
275 
276  if (test->arch) {
277  rz_pvector_push(&args, "-a");
278  rz_pvector_push(&args, (void *)test->arch);
279  }
280 
281  if (test->cpu) {
282  rz_pvector_push(&args, "-c");
283  rz_pvector_push(&args, (void *)test->cpu);
284  }
285 
286  char bits[0x20];
287  if (test->bits) {
288  snprintf(bits, sizeof(bits), "%d", test->bits);
289  rz_pvector_push(&args, "-b");
291  }
292 
293  if (test->mode & RZ_ASM_TEST_MODE_BIG_ENDIAN) {
294  rz_pvector_push(&args, "-e");
295  }
296 
297  char offset[0x20];
298  if (test->offset) {
299  rz_snprintf(offset, sizeof(offset), "0x%" PFMT64x, test->offset);
300  rz_pvector_push(&args, "-o");
302  }
303 
304  if (test->mode & RZ_ASM_TEST_MODE_ASSEMBLE) {
305  rz_pvector_push(&args, test->disasm);
307  if (rz_subprocess_wait(proc, config->timeout_ms) == RZ_SUBPROCESS_TIMEDOUT) {
309  out->as_timeout = true;
310  goto rip;
311  }
312  if (rz_subprocess_ret(proc) != 0) {
313  goto rip;
314  }
315  char *hex = (char *)crlf2lf(rz_subprocess_out(proc, NULL));
316  size_t hexlen = strlen(hex);
317  if (!hexlen) {
318  goto rip;
319  }
320  ut8 *bytes = malloc(hexlen);
321  int byteslen = rz_hex_str2bin(hex, bytes);
322  free(hex);
323  if (byteslen <= 0) {
324  free(bytes);
325  goto rip;
326  }
327  out->bytes = bytes;
328  out->bytes_size = (size_t)byteslen;
329  rip:
332  }
333  if (test->mode & RZ_ASM_TEST_MODE_DISASSEMBLE) {
334  char *hex = rz_hex_bin2strdup(test->bytes, test->bytes_size);
335  if (!hex) {
336  goto beach;
337  }
338  rz_pvector_push(&args, "-d");
341  if (rz_subprocess_wait(proc, config->timeout_ms) == RZ_SUBPROCESS_TIMEDOUT) {
343  out->disas_timeout = true;
344  goto ship;
345  }
346  if (rz_subprocess_ret(proc) != 0) {
347  goto ship;
348  }
349  char *disasm = (char *)crlf2lf(rz_subprocess_out(proc, NULL));
350  rz_str_trim(disasm);
351  out->disasm = disasm;
352  ship:
353  free(hex);
357  }
358  if (test->il) {
359  char *hex = rz_hex_bin2strdup(test->bytes, test->bytes_size);
360  if (!hex) {
361  goto beach;
362  }
363  rz_pvector_push(&args, "-I");
366  if (rz_subprocess_wait(proc, config->timeout_ms) == RZ_SUBPROCESS_TIMEDOUT) {
368  out->il_timeout = true;
369  } else {
370  char *il = (char *)crlf2lf(rz_subprocess_out(proc, NULL));
371  rz_str_trim(il);
372  char *il_err = (char *)crlf2lf(rz_subprocess_err(proc, NULL));
373  rz_str_trim(il_err);
374  out->il = il;
375  out->il_report = il_err;
376  out->il_failed = rz_subprocess_ret(proc) != 0;
377  }
378  free(hex);
382  }
383 
384 beach:
386  return out;
387 }
388 
390  if (!out) {
391  return false;
392  }
393  if (test->mode & RZ_ASM_TEST_MODE_ASSEMBLE) {
394  if (!out->bytes || !test->bytes || out->bytes_size != test->bytes_size || out->as_timeout) {
395  return false;
396  }
397  if (memcmp(out->bytes, test->bytes, test->bytes_size) != 0) {
398  return false;
399  }
400  }
401  if (test->mode & RZ_ASM_TEST_MODE_DISASSEMBLE) {
402  if (!out->disasm || !test->disasm || out->as_timeout) {
403  return false;
404  }
405  if (strcmp(out->disasm, test->disasm) != 0) {
406  return false;
407  }
408  }
409  if (test->il) {
410  // expect some IL, no failure, no report and no timeout
411  if (!out->il || out->il_failed || (out->il_report && *out->il_report) || out->il_timeout) {
412  return false;
413  }
414  // IL must also be correct
415  if (strcmp(out->il, test->il) != 0) {
416  return false;
417  }
418  }
419  return true;
420 }
421 
423  if (!out) {
424  return;
425  }
426  free(out->disasm);
427  free(out->bytes);
428  free(out->il);
429  free(out->il_report);
430  free(out);
431 }
432 
434  const char *cmd = "aaa";
435  RzList *files = rz_list_new();
436  rz_list_push(files, test->file);
437 #if ASAN
438  if (rz_str_endswith(test->file, "/swift_read")) {
439  cmd = "?F";
440  }
441 #endif
442  RzSubprocessOutput *ret = run_rz_test(config, config->timeout_ms, cmd, files, NULL, false, runner, user);
444  return ret;
445 }
446 
448  return out && out->ret == 0 && out->out && out->err && !out->timeout;
449 }
450 
452  switch (test->type) {
453  case RZ_TEST_TYPE_CMD:
454  if (test->cmd_test->name.value) {
455  return strdup(test->cmd_test->name.value);
456  }
457  return strdup("<unnamed>");
458  case RZ_TEST_TYPE_ASM:
459  return rz_str_newf("<asm> %s", test->asm_test->disasm ? test->asm_test->disasm : "");
460  case RZ_TEST_TYPE_JSON:
461  return rz_str_newf("<json> %s", test->json_test->cmd ? test->json_test->cmd : "");
462  case RZ_TEST_TYPE_FUZZ:
463  return rz_str_newf("<fuzz> %s", test->fuzz_test->file);
464  }
465  return NULL;
466 }
467 
469  switch (test->type) {
470  case RZ_TEST_TYPE_CMD:
471  return test->cmd_test->broken.value;
472  case RZ_TEST_TYPE_ASM:
473  return test->asm_test->mode & RZ_ASM_TEST_MODE_BROKEN ? true : false;
474  case RZ_TEST_TYPE_JSON:
475  return test->json_test->broken;
476  case RZ_TEST_TYPE_FUZZ:
477  return false;
478  }
479  return false;
480 }
481 
484  if (!ret) {
485  return NULL;
486  }
487  ret->test = test;
488  bool success = false;
490  switch (test->type) {
491  case RZ_TEST_TYPE_CMD: {
492  RzCmdTest *cmd_test = test->cmd_test;
494  success = rz_test_check_cmd_test(out, cmd_test);
495  ret->proc_out = out;
496  ret->timeout = out && out->timeout;
497  ret->run_failed = !out;
498  break;
499  }
500  case RZ_TEST_TYPE_ASM: {
501  RzAsmTest *asm_test = test->asm_test;
503  success = rz_test_check_asm_test(out, asm_test);
504  ret->asm_out = out;
505  if (out) {
506  ret->timeout = out->as_timeout || out->disas_timeout || out->il_timeout;
507  }
508  ret->run_failed = !out;
509  break;
510  }
511  case RZ_TEST_TYPE_JSON: {
512  RzJsonTest *json_test = test->json_test;
514  success = rz_test_check_json_test(out, json_test);
515  ret->proc_out = out;
516  if (out) {
517  ret->timeout = out->timeout;
518  }
519  ret->run_failed = !out;
520  break;
521  }
522  case RZ_TEST_TYPE_FUZZ: {
523  RzFuzzTest *fuzz_test = test->fuzz_test;
525  success = rz_test_check_fuzz_test(out);
526  ret->proc_out = out;
527  if (out) {
528  ret->timeout = out->timeout;
529  }
530  ret->run_failed = !out;
531  }
532  }
534  bool broken = rz_test_broken(test);
535 #if ASAN
536 #if !RZ_ASSERT_STDOUT
537 #error RZ_ASSERT_STDOUT undefined or 0
538 #endif
540  if (!success && test->type == RZ_TEST_TYPE_CMD && strstr(test->path, "/dbg") && (!out->out || (!strstr((char *)out->out, "WARNING:") && !strstr((char *)out->out, "ERROR:") && !strstr((char *)out->out, "FATAL:"))) && (!out->err || (!strstr((char *)out->err, "Sanitizer") && !strstr((char *)out->err, "runtime error:")))) {
541  broken = true;
542  }
543 #endif
544  if (!success) {
546  } else {
548  }
549  return ret;
550 }
551 
553  if (!result) {
554  return;
555  }
556  if (result->test) {
557  switch (result->test->type) {
558  case RZ_TEST_TYPE_CMD:
559  case RZ_TEST_TYPE_JSON:
560  case RZ_TEST_TYPE_FUZZ:
562  break;
563  case RZ_TEST_TYPE_ASM:
565  break;
566  }
567  }
568  free(result);
569 }
lzma_index * src
Definition: index.h:567
static ut8 bytes[32]
Definition: asm_arc.c:23
RZ_API bool rz_test_check_asm_test(RzAsmTestOutput *out, RzAsmTest *test)
Definition: run.c:389
RZ_API RzTestResultInfo * rz_test_run_test(RzTestRunConfig *config, RzTest *test)
Definition: run.c:482
#define crlf2lf(x)
Definition: run.c:24
RZ_API RzSubprocessOutput * rz_test_run_cmd_test(RzTestRunConfig *config, RzCmdTest *test, RzTestCmdRunner runner, void *user)
Definition: run.c:161
RZ_API bool rz_test_broken(RzTest *test)
Definition: run.c:468
RZ_API bool rz_test_check_jq_available(void)
Definition: run.c:223
RZ_API RzSubprocessOutput * rz_test_run_json_test(RzTestRunConfig *config, RzJsonTest *test, RzTestCmdRunner runner, void *user)
Definition: run.c:246
RZ_API RzAsmTestOutput * rz_test_run_asm_test(RzTestRunConfig *config, RzAsmTest *test)
Definition: run.c:267
RZ_API bool rz_test_check_json_test(RzSubprocessOutput *out, RzJsonTest *test)
Definition: run.c:254
static RzSubprocessOutput * subprocess_runner(const char *file, const char *args[], size_t args_size, const char *envvars[], const char *envvals[], size_t env_size, ut64 timeout_ms, void *user)
Definition: run.c:27
RZ_API bool rz_test_cmp_cmd_output(const char *output, const char *expect, const char *regexp)
Definition: run.c:192
#define JQ_CMD
Definition: run.c:221
RZ_API RzSubprocessOutput * rz_test_run_fuzz_test(RzTestRunConfig *config, RzFuzzTest *test, RzTestCmdRunner runner, void *user)
Definition: run.c:433
RZ_API bool rz_test_check_cmd_test(RzSubprocessOutput *out, RzCmdTest *test)
Definition: run.c:204
RZ_API void rz_test_test_result_info_free(RzTestResultInfo *result)
Definition: run.c:552
RZ_API void rz_test_asm_test_output_free(RzAsmTestOutput *out)
Definition: run.c:422
RZ_API bool rz_test_check_fuzz_test(RzSubprocessOutput *out)
Definition: run.c:447
static RzSubprocessOutput * run_rz_test(RzTestRunConfig *config, ut64 timeout_ms, const char *cmds, RzList *files, RzList *extra_args, bool load_plugins, RzTestCmdRunner runner, void *user)
Definition: run.c:113
RZ_API char * rz_test_test_name(RzTest *test)
Definition: run.c:451
int bits(struct state *s, int need)
Definition: blast.c:72
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
void rip(char *fname, off_t offset, unsigned int length)
Definition: cabrip.c:18
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
#define true
checking print the parsed form of the magic use in n conjunction with m to debug a new magic file n before installing it n output MIME type special files
Definition: file_opts.h:46
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API void rz_list_delete(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
Removes an entry in the list by using the RzListIter pointer.
Definition: list.c:162
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API RZ_OWN char * rz_list_to_str(RZ_NONNULL RzList *list, char ch)
Casts a RzList containg strings into a concatenated string.
Definition: list.c:785
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * malloc(size_t size)
Definition: malloc.c:123
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
#define expect(expr, value)
Definition: lz4.c:170
char * dest
Definition: lz4.h:697
int args
Definition: mipsasm.c:18
static uint64_t start_time
Definition: mytime.c:21
-lz4-versions
static const char hex[16]
Definition: print.c:21
RZ_API int rz_hex_str2bin(const char *in, ut8 *out)
Convert an input string in into the binary form in out.
Definition: hex.c:444
RZ_API char * rz_hex_bin2strdup(const ut8 *in, int len)
Definition: hex.c:415
RZ_API RzList * rz_regex_get_match_list(const char *pattern, const char *flags, const char *text)
Definition: regcomp.c:155
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API int rz_snprintf(char *string, int len, const char *fmt,...) RZ_PRINTF_CHECK(3
RZ_API RzList * rz_str_split_duplist(const char *str, const char *c, bool trim)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3464
RZ_API char * rz_str_replace(char *str, const char *key, const char *val, int g)
Definition: str.c:1110
RZ_API void rz_str_trim(RZ_NONNULL RZ_INOUT char *str)
Removes whitespace characters (space, tab, newline etc.) from the beginning and end of a string.
Definition: str_trim.c:190
RZ_API bool rz_str_endswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string ends with a specifc sequence of characters (case sensitive)
Definition: str.c:3329
RZ_API RzSubprocessOutput * rz_subprocess_drain(RzSubprocess *proc)
Definition: subprocess.c:1260
@ RZ_SUBPROCESS_TIMEDOUT
Definition: rz_subprocess.h:32
RZ_API RzSubprocessWaitReason rz_subprocess_wait(RzSubprocess *proc, ut64 timeout_ms)
Definition: subprocess.c:1185
RZ_API void rz_subprocess_free(RzSubprocess *proc)
Definition: subprocess.c:1273
RZ_API ut8 * rz_subprocess_out(RzSubprocess *proc, int *length)
Definition: subprocess.c:1301
enum rz_process_wait_reason_t RzSubprocessWaitReason
RZ_API RzSubprocess * rz_subprocess_start(const char *file, const char *args[], size_t args_size, const char *envvars[], const char *envvals[], size_t env_size)
Definition: subprocess.c:1345
RZ_API void rz_subprocess_output_free(RzSubprocessOutput *out)
Definition: subprocess.c:1323
RZ_API ut8 * rz_subprocess_err(RzSubprocess *proc, int *length)
Definition: subprocess.c:1312
RZ_API ssize_t rz_subprocess_stdin_write(RzSubprocess *proc, const ut8 *buf, size_t buf_size)
Definition: subprocess.c:1206
RZ_API int rz_subprocess_ret(RzSubprocess *proc)
Definition: subprocess.c:1297
RZ_API void rz_subprocess_kill(RzSubprocess *proc)
Definition: subprocess.c:1256
@ RZ_TEST_RESULT_OK
Definition: rz_test.h:162
@ RZ_TEST_RESULT_FAILED
Definition: rz_test.h:163
@ RZ_TEST_RESULT_FIXED
Definition: rz_test.h:165
@ RZ_TEST_RESULT_BROKEN
Definition: rz_test.h:164
RzSubprocessOutput *(* RzTestCmdRunner)(const char *file, const char *args[], size_t args_size, const char *envvars[], const char *envvals[], size_t env_size, ut64 timeout_ms, void *user)
Definition: rz_test.h:197
@ RZ_TEST_TYPE_JSON
Definition: rz_test.h:122
@ RZ_TEST_TYPE_ASM
Definition: rz_test.h:121
@ RZ_TEST_TYPE_FUZZ
Definition: rz_test.h:123
@ RZ_TEST_TYPE_CMD
Definition: rz_test.h:120
@ RZ_ASM_TEST_MODE_BIG_ENDIAN
Definition: rz_test.h:91
@ RZ_ASM_TEST_MODE_BROKEN
Definition: rz_test.h:92
@ RZ_ASM_TEST_MODE_ASSEMBLE
Definition: rz_test.h:89
@ RZ_ASM_TEST_MODE_DISASSEMBLE
Definition: rz_test.h:90
RZ_API ut64 rz_time_now_mono(void)
Returns the current time in microseconds, using the monotonic clock.
Definition: time.c:102
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define UT64_MAX
Definition: rz_types_base.h:86
RZ_API void * rz_pvector_pop(RzPVector *vec)
Definition: vector.c:372
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
Definition: vector.c:298
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_pvector_clear(RzPVector *vec)
Definition: vector.c:326
int size_t
Definition: sftypes.h:40
#define c(i)
Definition: sha256.c:43
Definition: gzappend.c:170
Definition: engine.c:71
RzAsmTestOutput * asm_out
Definition: rz_test.h:176
RzSubprocessOutput * proc_out
Definition: rz_test.h:175
RzTestType type
Definition: rz_test.h:128
struct Proc * proc
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
diff_output_t output
Definition: zipcmp.c:237