Rizin
unix-like reverse engineering framework and cli tools
funcs.c
Go to the documentation of this file.
1 /* $OpenBSD: funcs.c,v 1.7 2009/10/27 23:59:37 deraadt Exp $ */
2 /*
3  * Copyright (c) Christos Zoulas 2003.
4  * All Rights Reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice immediately at the beginning of the file, without modification,
11  * this list of conditions, and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <rz_userconf.h>
30 
31 #if !USE_LIB_MAGIC
32 
33 #include "file.h"
34 #include <stdarg.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <wctype.h>
39 #if defined(HAVE_WCHAR_H)
40 #include <wchar.h>
41 #endif
42 
43 // copypasta to fix an OPENBSDBUG
44 static int file_vprintf(RzMagic *ms, const char *fmt, va_list ap) {
45  va_list ap2;
46  char cbuf[4096];
47  char *buf, *newstr;
48 
49  va_copy(ap2, ap);
50  int len = vsnprintf(cbuf, sizeof(cbuf), fmt, ap2);
51  va_end(ap2);
52  if (len < 0) {
53  goto out;
54  }
55  if (len > sizeof(cbuf)) {
56  buf = malloc(len + 1);
57  va_copy(ap2, ap);
58  (void)vsnprintf(buf, len + 1, fmt, ap2);
59  va_end(ap2);
60  } else {
61  int nullbyte = len;
62  if (nullbyte > 0 && nullbyte == sizeof(cbuf)) {
63  nullbyte--;
64  }
65  cbuf[nullbyte] = 0;
66  buf = strdup(cbuf);
67  }
68  if (!buf) {
69  return -1;
70  }
71 
72  int buflen = len;
73  if (ms->o.buf) {
74  int obuflen = strlen(ms->o.buf);
75  len = obuflen + buflen + 1;
76  newstr = malloc(len);
77  if (!newstr) {
78  free(buf);
79  return -1;
80  }
81  memcpy(newstr, ms->o.buf, obuflen);
83  newstr[len - 1] = 0;
84  free(buf);
85  free(ms->o.buf);
86  if (len < 0) {
87  free(newstr);
88  goto out;
89  }
90  buf = newstr;
91  }
92  ms->o.buf = buf;
93  return 0;
94 out:
95  file_error(ms, errno, "vasprintf failed");
96  return -1;
97 }
98 
99 /*
100  * Like printf, only we append to a buffer.
101  */
102 int file_printf(RzMagic *ms, const char *fmt, ...) {
103  va_list ap;
104  int ret;
105 
106  va_start(ap, fmt);
107  ret = file_vprintf(ms, fmt, ap);
108  va_end(ap);
109  return ret;
110 }
111 
112 /*
113  * error - print best error message possible
114  */
115 /*VARARGS*/
116 static void file_error_core(RzMagic *ms, int error, const char *f, va_list va, ut32 lineno) {
117  /* Only the first error is ok */
118  if (!ms || ms->haderr) {
119  return;
120  }
121  if (lineno != 0) {
122  free(ms->o.buf);
123  ms->o.buf = NULL;
124  (void)file_printf(ms, "line %u: ", lineno);
125  }
126  // OPENBSDBUG
127  file_vprintf(ms, f, va);
128  if (error > 0) {
129  (void)file_printf(ms, " (%s)", strerror(error));
130  }
131  ms->haderr++;
132  ms->error = error;
133 }
134 
135 /*VARARGS*/
136 void file_error(RzMagic *ms, int error, const char *f, ...) {
137  va_list va;
138  va_start(va, f);
139  file_error_core(ms, error, f, va, 0);
140  va_end(va);
141 }
142 
143 /*
144  * Print an error with magic line number.
145  */
146 /*VARARGS*/
147 void file_magerror(RzMagic *ms, const char *f, ...) {
148  va_list va;
149  va_start(va, f);
150  file_error_core(ms, 0, f, va, ms->line);
151  va_end(va);
152 }
153 
154 void file_oomem(RzMagic *ms, size_t len) {
155  file_error(ms, errno, "cannot allocate %zu bytes", len);
156 }
157 
158 void file_badseek(RzMagic *ms) {
159  file_error(ms, errno, "error seeking");
160 }
161 
162 void file_badread(RzMagic *ms) {
163  file_error(ms, errno, "error reading");
164 }
165 
166 int file_buffer(RzMagic *ms, int fd, const char *inname, const void *buf, size_t nb) {
167  int mime, m = 0;
168  if (!ms) {
169  return -1;
170  }
171  mime = ms->flags & RZ_MAGIC_MIME;
172  if (nb == 0) {
173  if ((!mime || (mime & RZ_MAGIC_MIME_TYPE)) &&
174  file_printf(ms, mime ? "application/x-empty" : "empty") == -1) {
175  return -1;
176  }
177  return 1;
178  } else if (nb == 1) {
179  if ((!mime || (mime & RZ_MAGIC_MIME_TYPE)) &&
180  file_printf(ms, mime ? "application/octet-stream" : "very short file (no magic)") == -1) {
181  return -1;
182  }
183  return 1;
184  }
185 
186 #if 0
187  /* try compression stuff */
188  if ((ms->flags & RZ_MAGIC_NO_CHECK_COMPRESS) != 0 ||
189  (m = file_zmagic(ms, fd, inname, buf, nb)) == 0) {
190 #endif
191  /* Check if we have a tar file */
192  if ((ms->flags & RZ_MAGIC_NO_CHECK_TAR) != 0 ||
193  (m = file_is_tar(ms, buf, nb)) == 0) {
194  /* try tests in /etc/magic (or surrogate magic file) */
195  if ((ms->flags & RZ_MAGIC_NO_CHECK_SOFT) != 0 ||
196  (m = file_softmagic(ms, buf, nb, BINTEST)) == 0) {
197  /* try known keywords, check whether it is ASCII */
198  if ((ms->flags & RZ_MAGIC_NO_CHECK_ASCII) != 0 ||
199  (m = file_ascmagic(ms, buf, nb)) == 0) {
200  /* abandon hope, all ye who remain here */
201  if ((!mime || (mime & RZ_MAGIC_MIME_TYPE))) {
202  // if (mime)
203  file_printf(ms, "application/octet-stream");
204  return -1;
205  }
206  m = 1;
207  }
208  }
209  }
210 #if 0
211  }
212 #endif
213  return m;
214 }
215 
216 int file_reset(RzMagic *ms) {
217  if (!ms) {
218  return 0;
219  }
220  free(ms->o.buf);
221  ms->o.buf = NULL;
222  ms->haderr = 0;
223  ms->error = -1;
224  if (!ms->mlist) {
225  file_error(ms, 0, "no magic files loaded! ");
226  return -1;
227  }
228  return 0;
229 }
230 
231 #define OCTALIFY(n, o) \
232  /*LINTED*/ \
233  (void)(*(n)++ = '\\', \
234  *(n)++ = (((ut32) * (o) >> 6) & 3) + '0', \
235  *(n)++ = (((ut32) * (o) >> 3) & 7) + '0', \
236  *(n)++ = (((ut32) * (o) >> 0) & 7) + '0', \
237  (o)++)
238 
239 const char *file_getbuffer(RzMagic *ms) {
240  char *pbuf, *op, *np;
241  size_t psize, len;
242 
243  if (ms->haderr) {
244  return NULL;
245  }
246 
247  if (ms->flags & RZ_MAGIC_RAW) {
248  return ms->o.buf;
249  }
250 
251  if (!ms->o.buf) {
252  eprintf("ms->o.buf = NULL\n");
253  return NULL;
254  }
255 
256  /* * 4 is for octal representation, + 1 is for NUL */
257  len = strlen(ms->o.buf);
258  if (len > (SIZE_MAX - 1) / 4) {
259  file_oomem(ms, len);
260  return NULL;
261  }
262  psize = len * 4 + 1;
263  if (!(pbuf = realloc(ms->o.pbuf, psize))) {
264  file_oomem(ms, psize);
265  return NULL;
266  }
267  ms->o.pbuf = pbuf;
268 
269 #if 1
270  // defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
271  {
272  mbstate_t state;
273  wchar_t nextchar;
274  int mb_conv = 1;
275  size_t bytesconsumed;
276  char *eop;
277  (void)memset(&state, 0, sizeof(mbstate_t));
278 
279  np = ms->o.pbuf;
280  op = ms->o.buf;
281  eop = op + len;
282 
283  while (op < eop) {
284  bytesconsumed = mbrtowc(&nextchar, op,
285  (size_t)(eop - op), &state);
286  if (bytesconsumed == (size_t)(-1) ||
287  bytesconsumed == (size_t)(-2)) {
288  mb_conv = 0;
289  break;
290  }
291 
292  if (iswprint(nextchar)) {
293  (void)memcpy(np, op, bytesconsumed);
294  op += bytesconsumed;
295  np += bytesconsumed;
296  } else {
297  while (bytesconsumed-- > 0) {
298  OCTALIFY(np, op);
299  }
300  }
301  }
302  *np = '\0';
303 
304  /* Parsing succeeded as a multi-byte sequence */
305  if (mb_conv != 0) {
306  return ms->o.pbuf;
307  }
308  }
309 #endif
310  for (np = ms->o.pbuf, op = ms->o.buf; *op; op++) {
311  if (isprint((ut8)*op)) {
312  *np++ = *op;
313  } else {
314  OCTALIFY(np, op);
315  }
316  }
317  *np = '\0';
318  return ms->o.pbuf;
319 }
320 
321 int file_check_mem(RzMagic *ms, unsigned int level) {
322  if (level >= ms->c.len) {
323  size_t len = (ms->c.len += 20) * sizeof(*ms->c.li);
324  ms->c.li = (!ms->c.li) ? malloc(len) : realloc(ms->c.li, len);
325  if (!ms->c.li) {
326  file_oomem(ms, len);
327  return -1;
328  }
329  }
330  ms->c.li[level].got_match = 0;
331  ms->c.li[level].last_match = 0;
332  ms->c.li[level].last_cond = COND_NONE;
333  return 0;
334 }
335 #endif
size_t len
Definition: 6502dis.c:15
ut8 op
Definition: 6502dis.c:13
int file_ascmagic(RzMagic *ms, const ut8 *buf, size_t nbytes)
Definition: ascmagic.c:65
static RASN1String * newstr(const char *string)
Definition: astr.c:23
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
int file_is_tar(struct rz_magic_set *, const unsigned char *, size_t)
int file_zmagic(struct rz_magic_set *, int, const char *, const ut8 *, size_t)
int file_softmagic(struct rz_magic_set *, const unsigned char *, size_t, int)
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 mime
Definition: file_opts.h:30
void file_oomem(RzMagic *ms, size_t len)
Definition: funcs.c:154
int file_check_mem(RzMagic *ms, unsigned int level)
Definition: funcs.c:321
int file_buffer(RzMagic *ms, int fd, const char *inname, const void *buf, size_t nb)
Definition: funcs.c:166
static void file_error_core(RzMagic *ms, int error, const char *f, va_list va, ut32 lineno)
Definition: funcs.c:116
const char * file_getbuffer(RzMagic *ms)
Definition: funcs.c:239
#define OCTALIFY(n, o)
Definition: funcs.c:231
int file_printf(RzMagic *ms, const char *fmt,...)
Definition: funcs.c:102
void file_magerror(RzMagic *ms, const char *f,...)
Definition: funcs.c:147
void file_error(RzMagic *ms, int error, const char *f,...)
Definition: funcs.c:136
int file_reset(RzMagic *ms)
Definition: funcs.c:216
static int file_vprintf(RzMagic *ms, const char *fmt, va_list ap)
Definition: funcs.c:44
void file_badread(RzMagic *ms)
Definition: funcs.c:162
void file_badseek(RzMagic *ms)
Definition: funcs.c:158
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
vsnprintf
Definition: kernel.h:366
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
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 eprintf(x, y...)
Definition: rlcc.c:7
#define isprint(c)
Definition: safe-ctype.h:137
#define f(i)
Definition: sha256.c:46
#define SIZE_MAX
Definition: dis.h:43
static char * nextchar
Definition: getopt.c:142
ut64 buflen
Definition: core.c:76
Definition: dis.c:32
void error(const char *msg)
Definition: untgz.c:593
static int level
Definition: vmenus.c:2424
static const z80_opcode fd[]
Definition: z80_tab.h:997
static int obuflen
Definition: z80asm.c:37