summaryrefslogtreecommitdiff
path: root/src/funcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/funcs.c')
-rw-r--r--src/funcs.c138
1 files changed, 127 insertions, 11 deletions
diff --git a/src/funcs.c b/src/funcs.c
index 9cdec0182661..09b965e9a9c2 100644
--- a/src/funcs.c
+++ b/src/funcs.c
@@ -27,7 +27,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: funcs.c,v 1.108 2019/11/09 00:35:46 christos Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.115 2020/02/20 15:50:20 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -48,6 +48,77 @@ FILE_RCSID("@(#)$File: funcs.c,v 1.108 2019/11/09 00:35:46 christos Exp $")
#define SIZE_MAX ((size_t)~0)
#endif
+protected char *
+file_copystr(char *buf, size_t blen, size_t width, const char *str)
+{
+ if (++width > blen)
+ width = blen;
+ strlcpy(buf, str, width);
+ return buf;
+}
+
+private void
+file_clearbuf(struct magic_set *ms)
+{
+ free(ms->o.buf);
+ ms->o.buf = NULL;
+ ms->o.blen = 0;
+}
+
+private int
+file_checkfield(char *msg, size_t mlen, const char *what, const char **pp)
+{
+ const char *p = *pp;
+ int fw = 0;
+
+ while (*p && isdigit((unsigned char)*p))
+ fw = fw * 10 + (*p++ - '0');
+
+ *pp = p;
+
+ if (fw < 1024)
+ return 1;
+ if (msg)
+ snprintf(msg, mlen, "field %s too large: %d", what, fw);
+
+ return 0;
+}
+
+protected int
+file_checkfmt(char *msg, size_t mlen, const char *fmt)
+{
+ for (const char *p = fmt; *p; p++) {
+ if (*p != '%')
+ continue;
+ if (*++p == '%')
+ continue;
+ // Skip uninteresting.
+ while (strchr("0.'+- ", *p) != NULL)
+ p++;
+ if (*p == '*') {
+ if (msg)
+ snprintf(msg, mlen, "* not allowed in format");
+ return -1;
+ }
+
+ if (!file_checkfield(msg, mlen, "width", &p))
+ return -1;
+
+ if (*p == '.') {
+ p++;
+ if (!file_checkfield(msg, mlen, "precision", &p))
+ return -1;
+ }
+
+ if (!isalpha((unsigned char)*p)) {
+ if (msg)
+ snprintf(msg, mlen, "bad format char: %c", *p);
+ return -1;
+ }
+ }
+ return 0;
+}
+
/*
* Like printf, only we append to a buffer.
*/
@@ -56,12 +127,26 @@ file_vprintf(struct magic_set *ms, const char *fmt, va_list ap)
{
int len;
char *buf, *newstr;
+ char tbuf[1024];
if (ms->event_flags & EVENT_HAD_ERR)
return 0;
+
+ if (file_checkfmt(tbuf, sizeof(tbuf), fmt)) {
+ file_clearbuf(ms);
+ file_error(ms, 0, "Bad magic format `%s' (%s)", fmt, tbuf);
+ return -1;
+ }
+
len = vasprintf(&buf, fmt, ap);
- if (len < 0)
- goto out;
+ if (len < 0 || (size_t)len > 1024 || len + ms->o.blen > 1024 * 1024) {
+ size_t blen = ms->o.blen;
+ free(buf);
+ file_clearbuf(ms);
+ file_error(ms, 0, "Output buffer space exceeded %d+%zu", len,
+ blen);
+ return -1;
+ }
if (ms->o.buf != NULL) {
len = asprintf(&newstr, "%s%s", ms->o.buf, buf);
@@ -72,9 +157,11 @@ file_vprintf(struct magic_set *ms, const char *fmt, va_list ap)
buf = newstr;
}
ms->o.buf = buf;
+ ms->o.blen = len;
return 0;
out:
- fprintf(stderr, "vasprintf failed (%s)", strerror(errno));
+ file_clearbuf(ms);
+ file_error(ms, errno, "vasprintf failed");
return -1;
}
@@ -103,8 +190,7 @@ file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
if (ms->event_flags & EVENT_HAD_ERR)
return;
if (lineno != 0) {
- free(ms->o.buf);
- ms->o.buf = NULL;
+ file_clearbuf(ms);
(void)file_printf(ms, "line %" SIZE_T_FORMAT "u:", lineno);
}
if (ms->o.buf && *ms->o.buf)
@@ -393,10 +479,7 @@ file_reset(struct magic_set *ms, int checkloaded)
file_error(ms, 0, "no magic files loaded");
return -1;
}
- if (ms->o.buf) {
- free(ms->o.buf);
- ms->o.buf = NULL;
- }
+ file_clearbuf(ms);
if (ms->o.pbuf) {
free(ms->o.pbuf);
ms->o.pbuf = NULL;
@@ -518,7 +601,7 @@ file_check_mem(struct magic_set *ms, unsigned int level)
protected size_t
file_printedlen(const struct magic_set *ms)
{
- return ms->o.buf == NULL ? 0 : strlen(ms->o.buf);
+ return ms->o.blen;
}
protected int
@@ -614,9 +697,11 @@ file_push_buffer(struct magic_set *ms)
return NULL;
pb->buf = ms->o.buf;
+ pb->blen = ms->o.blen;
pb->offset = ms->offset;
ms->o.buf = NULL;
+ ms->o.blen = 0;
ms->offset = 0;
return pb;
@@ -636,6 +721,7 @@ file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb)
rbuf = ms->o.buf;
ms->o.buf = pb->buf;
+ ms->o.blen = pb->blen;
ms->offset = pb->offset;
free(pb);
@@ -667,3 +753,33 @@ file_printable(char *buf, size_t bufsiz, const char *str, size_t slen)
*ptr = '\0';
return buf;
}
+
+struct guid {
+ uint32_t data1;
+ uint16_t data2;
+ uint16_t data3;
+ uint8_t data4[8];
+};
+
+protected int
+file_parse_guid(const char *s, uint64_t *guid)
+{
+ struct guid *g = CAST(struct guid *, guid);
+ return sscanf(s,
+ "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
+ &g->data1, &g->data2, &g->data3, &g->data4[0], &g->data4[1],
+ &g->data4[2], &g->data4[3], &g->data4[4], &g->data4[5],
+ &g->data4[6], &g->data4[7]) == 11 ? 0 : -1;
+}
+
+protected int
+file_print_guid(char *str, size_t len, const uint64_t *guid)
+{
+ const struct guid *g = CAST(const struct guid *, guid);
+
+ return snprintf(str, len, "%.8X-%.4hX-%.4hX-%.2hhX%.2hhX-"
+ "%.2hhX%.2hhX%.2hhX%.2hhX%.2hhX%.2hhX",
+ g->data1, g->data2, g->data3, g->data4[0], g->data4[1],
+ g->data4[2], g->data4[3], g->data4[4], g->data4[5],
+ g->data4[6], g->data4[7]);
+}