698 lines
17 KiB
Diff
698 lines
17 KiB
Diff
--- gv-3.5.8/source/Imakefile.security Fri Sep 20 13:54:53 2002
|
|
+++ gv-3.5.8/source/Imakefile Fri Sep 20 13:55:18 2002
|
|
@@ -63,6 +63,7 @@
|
|
resource.c\
|
|
save.c\
|
|
scale.c\
|
|
+ secscanf.c\
|
|
signal.c\
|
|
version.c\
|
|
widgets_misc.c\
|
|
@@ -106,6 +107,7 @@
|
|
resource.o\
|
|
save.o\
|
|
scale.o\
|
|
+ secscanf.o\
|
|
signal.o\
|
|
version.o\
|
|
widgets_misc.o\
|
|
--- gv-3.5.8/source/ps.c.security Fri Sep 20 13:54:53 2002
|
|
+++ gv-3.5.8/source/ps.c Fri Sep 20 13:54:53 2002
|
|
@@ -93,6 +93,8 @@
|
|
#define memset(a,b,c) bzero(a,c)
|
|
#endif
|
|
|
|
+extern int sec_scanf(const char *, const char *, ...);
|
|
+
|
|
/* length calculates string length at compile time */
|
|
/* can only be used with character constants */
|
|
#define length(a) (sizeof((a))-1)
|
|
@@ -483,7 +485,7 @@
|
|
doc = (struct document *) PS_malloc(sizeof(struct document));
|
|
CHECK_MALLOCED(doc);
|
|
memset(doc, 0, sizeof(struct document));
|
|
- sscanf(line, "%*s %s", text);
|
|
+ sec_sscanf(line, "%*s %s", text, sizeof(text));
|
|
/*###jp###*/
|
|
/*doc->epsf = iscomment(text, "EPSF-");*/
|
|
doc->epsf = iscomment(text, "EPSF");
|
|
@@ -576,7 +578,7 @@
|
|
} else if (doc->date == NULL && iscomment(line+2, "CreationDate:")) {
|
|
doc->date = gettextline(line+length("%%CreationDate:"));
|
|
} else if (bb_set == NONE && iscomment(line+2, "BoundingBox:")) {
|
|
- sscanf(line+length("%%BoundingBox:"), "%s", text);
|
|
+ sec_sscanf(line+length("%%BoundingBox:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "(atend)") == 0) {
|
|
bb_set = ATEND;
|
|
} else {
|
|
@@ -608,7 +610,7 @@
|
|
}
|
|
} else if (orientation_set == NONE &&
|
|
iscomment(line+2, "Orientation:")) {
|
|
- sscanf(line+length("%%Orientation:"), "%s", text);
|
|
+ sec_sscanf(line+length("%%Orientation:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "(atend)") == 0) {
|
|
orientation_set = ATEND;
|
|
} else if (strcmp(text, "Portrait") == 0) {
|
|
@@ -619,7 +621,7 @@
|
|
orientation_set = 1;
|
|
}
|
|
} else if (page_order_set == NONE && iscomment(line+2, "PageOrder:")) {
|
|
- sscanf(line+length("%%PageOrder:"), "%s", text);
|
|
+ sec_sscanf(line+length("%%PageOrder:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "(atend)") == 0) {
|
|
page_order_set = ATEND;
|
|
} else if (strcmp(text, "Ascend") == 0) {
|
|
@@ -633,7 +635,7 @@
|
|
page_order_set = 1;
|
|
}
|
|
} else if (pages_set == NONE && iscomment(line+2, "Pages:")) {
|
|
- sscanf(line+length("%%Pages:"), "%s", text);
|
|
+ sec_sscanf(line+length("%%Pages:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "(atend)") == 0) {
|
|
pages_set = ATEND;
|
|
} else {
|
|
@@ -853,7 +855,7 @@
|
|
/* Do nothing */
|
|
} else if (doc->default_page_orientation == NONE &&
|
|
iscomment(line+2, "PageOrientation:")) {
|
|
- sscanf(line+length("%%PageOrientation:"), "%s", text);
|
|
+ sec_sscanf(line+length("%%PageOrientation:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "Portrait") == 0) {
|
|
doc->default_page_orientation = PORTRAIT;
|
|
} else if (strcmp(text, "Landscape") == 0) {
|
|
@@ -975,7 +977,7 @@
|
|
/* Do nothing */
|
|
} else if (doc->default_page_orientation == NONE &&
|
|
iscomment(line+2, "PageOrientation:")) {
|
|
- sscanf(line+length("%%PageOrientation:"), "%s", text);
|
|
+ sec_sscanf(line+length("%%PageOrientation:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "Portrait") == 0) {
|
|
doc->default_page_orientation = PORTRAIT;
|
|
} else if (strcmp(text, "Landscape") == 0) {
|
|
@@ -1112,7 +1114,7 @@
|
|
/* Do nothing */
|
|
} else if (doc->pages[doc->numpages].orientation == NONE &&
|
|
iscomment(line+2, "PageOrientation:")) {
|
|
- sscanf(line+length("%%PageOrientation:"), "%s", text);
|
|
+ sec_sscanf(line+length("%%PageOrientation:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "Portrait") == 0) {
|
|
doc->pages[doc->numpages].orientation = PORTRAIT;
|
|
} else if (strcmp(text, "Landscape") == 0) {
|
|
@@ -1144,7 +1146,7 @@
|
|
PS_free(cp);
|
|
} else if ((page_bb_set == NONE || page_bb_set == ATEND) &&
|
|
iscomment(line+2, "PageBoundingBox:")) {
|
|
- sscanf(line+length("%%PageBoundingBox:"), "%s", text);
|
|
+ sec_sscanf(line+length("%%PageBoundingBox:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "(atend)") == 0) {
|
|
page_bb_set = ATEND;
|
|
} else {
|
|
@@ -1258,14 +1260,14 @@
|
|
}
|
|
} else if (orientation_set == ATEND &&
|
|
iscomment(line+2, "Orientation:")) {
|
|
- sscanf(line+length("%%Orientation:"), "%s", text);
|
|
+ sec_sscanf(line+length("%%Orientation:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "Portrait") == 0) {
|
|
doc->orientation = PORTRAIT;
|
|
} else if (strcmp(text, "Landscape") == 0) {
|
|
doc->orientation = LANDSCAPE;
|
|
}
|
|
} else if (page_order_set == ATEND && iscomment(line+2, "PageOrder:")) {
|
|
- sscanf(line+length("%%PageOrder:"), "%s", text);
|
|
+ sec_sscanf(line+length("%%PageOrder:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "Ascend") == 0) {
|
|
doc->pageorder = ASCEND;
|
|
} else if (strcmp(text, "Descend") == 0) {
|
|
@@ -1819,7 +1821,7 @@
|
|
INFMESSAGE(encountered "BeginData:")
|
|
if (FD_LINE_LEN > 100) FD_BUF[100] = '\0';
|
|
text[0] = '\0';
|
|
- if (sscanf(line+length("%%BeginData:"), "%d %*s %s", &num, text) >= 1) {
|
|
+ if (sec_sscanf(line+length("%%BeginData:"), "%d %*s %s", &num, text, sizeof(text)) >= 1) {
|
|
if (strcmp(text, "Lines") == 0) {
|
|
INFIMESSAGE(number of lines to skip:,num)
|
|
while (num) {
|
|
@@ -1918,7 +1920,7 @@
|
|
INFMESSAGE(encountered "BeginData:")
|
|
if (FD_LINE_LEN > 100) FD_BUF[100] = '\0';
|
|
text[0] = '\0';
|
|
- if (sscanf(line+length("%%BeginData:"), "%d %*s %s", &num, text) >= 1) {
|
|
+ if (sec_sscanf(line+length("%%BeginData:"), "%d %*s %s", &num, text, sizeof(text)) >= 1) {
|
|
if (strcmp(text, "Lines") == 0) {
|
|
INFIMESSAGE(number of lines:,num)
|
|
while (num) {
|
|
@@ -2015,7 +2017,7 @@
|
|
PS_free(comment);
|
|
continue;
|
|
}
|
|
- sscanf(comment+length("%%Pages:"), "%s", text);
|
|
+ sec_sscanf(comment+length("%%Pages:"), "%s", text, sizeof(text));
|
|
if (strcmp(text, "(atend)") == 0) {
|
|
fputs(comment, dest_file);
|
|
pages_atend = True;
|
|
--- gv-3.5.8/source/secscanf.c.security Fri Sep 20 13:54:53 2002
|
|
+++ gv-3.5.8/source/secscanf.c Fri Sep 20 13:54:53 2002
|
|
@@ -0,0 +1,540 @@
|
|
+/*
|
|
+ * Secure sscanf - sscanf with an additional size argument for string
|
|
+ * arguments. All format specifiers should work as in the standard
|
|
+ * scanf - except for those writing to a string buffer provided by the
|
|
+ * caller. These specifiers take an additional argument of type size_t
|
|
+ * that specifies the size of the buffer.
|
|
+ *
|
|
+ * Copyright (C) 2002, Olaf Kirch <okir@suse.de>
|
|
+ */
|
|
+
|
|
+#define _GNU_SOURCE
|
|
+
|
|
+#include <sys/param.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <stdarg.h>
|
|
+#include <string.h>
|
|
+#include <ctype.h>
|
|
+
|
|
+enum {
|
|
+ CONV_ANY,
|
|
+ CONV_STR,
|
|
+ CONV_NUM,
|
|
+ CONV_INTEGER,
|
|
+ CONV_FLOAT,
|
|
+ CONV_POINTER,
|
|
+};
|
|
+
|
|
+enum {
|
|
+ SIZE_ANY,
|
|
+ SIZE_SHORT,
|
|
+ SIZE_LONG,
|
|
+ SIZE_QUAD,
|
|
+};
|
|
+
|
|
+union scan_value {
|
|
+ const char * v_string;
|
|
+ long long v_signed;
|
|
+ unsigned long long v_integer;
|
|
+ long double v_double;
|
|
+ void * v_pointer;
|
|
+};
|
|
+
|
|
+
|
|
+static int process_number(union scan_value *vp, const char **sp, char fmt);
|
|
+static int process_char_class(const char **, const char **, int);
|
|
+
|
|
+static inline int
|
|
+set_conv_type(int *type, int new_type)
|
|
+{
|
|
+ switch (*type) {
|
|
+ case CONV_ANY:
|
|
+ break;
|
|
+ case CONV_NUM:
|
|
+ if (new_type == CONV_INTEGER
|
|
+ || new_type == CONV_FLOAT
|
|
+ || new_type == CONV_POINTER)
|
|
+ break;
|
|
+ /* fallthru */
|
|
+ default:
|
|
+ if (*type != new_type)
|
|
+ return 0;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ *type = new_type;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+int
|
|
+sec_sscanf(const char *s, const char *fmt, ...)
|
|
+{
|
|
+ const char *begin = s;
|
|
+ int num_fields = 0, fmt_empty = 1;
|
|
+ va_list ap;
|
|
+
|
|
+ va_start(ap, fmt);
|
|
+ while (*fmt) {
|
|
+ union scan_value value;
|
|
+ const char *pre_space_skip,
|
|
+ *value_begin;
|
|
+ int assign = 1, allocate = 0,
|
|
+ conv_type = CONV_ANY,
|
|
+ conv_size = SIZE_ANY,
|
|
+ field_width = -1,
|
|
+ nul_terminated = 1;
|
|
+ char c;
|
|
+
|
|
+ c = *fmt++;
|
|
+ if (isspace(c)) {
|
|
+ while (isspace(*s))
|
|
+ s++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ fmt_empty = 0;
|
|
+ if (c != '%') {
|
|
+ if (c != *s)
|
|
+ goto stop;
|
|
+ s++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* Each % directive implicitly skips white space
|
|
+ * except for the %c case */
|
|
+ pre_space_skip = s;
|
|
+ while (isspace(*s))
|
|
+ s++;
|
|
+
|
|
+ while (1) {
|
|
+ int type = CONV_ANY, size = SIZE_ANY;
|
|
+
|
|
+ switch (*fmt) {
|
|
+ case '*':
|
|
+ assign = 0;
|
|
+ break;
|
|
+ case 'a':
|
|
+ type = CONV_STR;
|
|
+ allocate = 1;
|
|
+ break;
|
|
+ case 'h':
|
|
+ type = CONV_INTEGER;
|
|
+ size = SIZE_SHORT;
|
|
+ break;
|
|
+ case 'l':
|
|
+ type = CONV_NUM;
|
|
+ size = SIZE_LONG;
|
|
+ break;
|
|
+ case 'L':
|
|
+ case 'q':
|
|
+ type = CONV_NUM;
|
|
+ size = SIZE_QUAD;
|
|
+ break;
|
|
+ case '0': case '1': case '2': case '3': case '4':
|
|
+ case '5': case '6': case '7': case '8': case '9':
|
|
+ field_width = strtol(fmt, (char **) &fmt, 10);
|
|
+ fmt--;
|
|
+ break;
|
|
+ default:
|
|
+ goto flags_done;
|
|
+ }
|
|
+
|
|
+ if (!set_conv_type(&conv_type, type))
|
|
+ goto stop;
|
|
+
|
|
+ if (size != SIZE_ANY) {
|
|
+ if (size == SIZE_LONG && conv_size == SIZE_LONG)
|
|
+ conv_size = SIZE_QUAD;
|
|
+ else
|
|
+ conv_size = size;
|
|
+ }
|
|
+
|
|
+ fmt++;
|
|
+ }
|
|
+
|
|
+ flags_done:
|
|
+ value_begin = s;
|
|
+
|
|
+ switch (*fmt++) {
|
|
+ case '%':
|
|
+ if (*s == '\0')
|
|
+ goto eof;
|
|
+ if (*s != '%')
|
|
+ goto stop;
|
|
+ continue;
|
|
+ case '[':
|
|
+ value.v_string = s;
|
|
+ if (!set_conv_type(&conv_type, CONV_STR)
|
|
+ || !process_char_class(&fmt, &s, field_width))
|
|
+ goto stop;
|
|
+ break;
|
|
+ case 's':
|
|
+ value.v_string = s;
|
|
+ if (!set_conv_type(&conv_type, CONV_STR))
|
|
+ goto stop;
|
|
+ while (*s && !isspace(*s) && field_width-- != 0)
|
|
+ s++;
|
|
+ break;
|
|
+ case 'c':
|
|
+ if (!set_conv_type(&conv_type, CONV_STR))
|
|
+ goto stop;
|
|
+ value.v_string = s = value_begin = pre_space_skip;
|
|
+
|
|
+ if (field_width < 0)
|
|
+ s++;
|
|
+ else while (*s && field_width--)
|
|
+ s++;
|
|
+ nul_terminated = 0;
|
|
+ break;
|
|
+ case 'd':
|
|
+ case 'i':
|
|
+ case 'o':
|
|
+ case 'u':
|
|
+ case 'x':
|
|
+ case 'X':
|
|
+ if (!set_conv_type(&conv_type, CONV_INTEGER)
|
|
+ || !process_number(&value, &s, fmt[-1]))
|
|
+ goto stop;
|
|
+ break;
|
|
+ case 'p':
|
|
+ if (!set_conv_type(&conv_type, CONV_POINTER)
|
|
+ || !process_number(&value, &s, fmt[-1]))
|
|
+ goto stop;
|
|
+ break;
|
|
+ case 'f':
|
|
+ case 'g':
|
|
+ case 'e':
|
|
+ case 'E':
|
|
+ if (!set_conv_type(&conv_type, CONV_FLOAT)
|
|
+ || !process_number(&value, &s, fmt[-1]))
|
|
+ goto stop;
|
|
+ break;
|
|
+ case 'n':
|
|
+ if (!set_conv_type(&conv_type, CONV_INTEGER))
|
|
+ goto stop;
|
|
+ value.v_signed = (s - begin);
|
|
+ break;
|
|
+ default:
|
|
+ goto stop;
|
|
+ }
|
|
+
|
|
+ /* We've consumed what we need to consume. Now copy */
|
|
+ if (!assign)
|
|
+ continue;
|
|
+
|
|
+ /* Make sure we've consumed at least *something* */
|
|
+ if (s == value_begin)
|
|
+ goto eof;
|
|
+
|
|
+ /* Deal with a conversion flag */
|
|
+ if (conv_type == CONV_STR && allocate) {
|
|
+ value.v_pointer = strndup(value.v_string, s - value.v_string);
|
|
+ conv_type = CONV_POINTER;
|
|
+ allocate = 0;
|
|
+ }
|
|
+
|
|
+ switch (conv_type) {
|
|
+ case CONV_STR:
|
|
+ {
|
|
+ const char *string = value.v_string;
|
|
+ char *buf;
|
|
+ size_t size;
|
|
+
|
|
+ if (string == NULL)
|
|
+ goto stop;
|
|
+ buf = va_arg(ap, char *);
|
|
+ size = va_arg(ap, size_t) - nul_terminated;
|
|
+ if (size > s - string)
|
|
+ size = s - string;
|
|
+ strncpy(buf, string, size);
|
|
+ if (nul_terminated)
|
|
+ buf[size] = '\0';
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case CONV_POINTER:
|
|
+ {
|
|
+ void **ptr;
|
|
+
|
|
+ ptr = va_arg(ap, void **);
|
|
+ *ptr = value.v_pointer;
|
|
+ }
|
|
+ break;
|
|
+ case CONV_INTEGER:
|
|
+ {
|
|
+ void *ptr;
|
|
+
|
|
+ ptr = va_arg(ap, void *);
|
|
+ switch (conv_size) {
|
|
+ case SIZE_SHORT:
|
|
+ *(short *) ptr = value.v_integer;
|
|
+ break;
|
|
+ case SIZE_ANY:
|
|
+ *(int *) ptr = value.v_integer;
|
|
+ break;
|
|
+ case SIZE_LONG:
|
|
+ *(long *) ptr = value.v_integer;
|
|
+ break;
|
|
+ case SIZE_QUAD:
|
|
+ *(long long *) ptr = value.v_integer;
|
|
+ break;
|
|
+ default:
|
|
+ goto stop;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ case CONV_FLOAT:
|
|
+ {
|
|
+ void *ptr;
|
|
+
|
|
+ ptr = va_arg(ap, void *);
|
|
+ switch (conv_size) {
|
|
+ case SIZE_ANY:
|
|
+ *(float *) ptr = value.v_double;
|
|
+ break;
|
|
+ case SIZE_LONG:
|
|
+ *(double *) ptr = value.v_double;
|
|
+ break;
|
|
+ case SIZE_QUAD:
|
|
+ *(long double *) ptr = value.v_double;
|
|
+ break;
|
|
+ default:
|
|
+ goto stop;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ goto stop;
|
|
+ }
|
|
+
|
|
+ num_fields++;
|
|
+ }
|
|
+
|
|
+stop: return num_fields;
|
|
+
|
|
+eof: if (num_fields)
|
|
+ return num_fields;
|
|
+ return EOF;
|
|
+}
|
|
+
|
|
+static int
|
|
+process_number(union scan_value *vp, const char **sp, char fmt)
|
|
+{
|
|
+ const char *s = *sp;
|
|
+
|
|
+ switch (fmt) {
|
|
+ case 'd':
|
|
+ vp->v_signed = strtoll(s, (char **) sp, 10);
|
|
+ break;
|
|
+ case 'i':
|
|
+ vp->v_signed = strtoll(s, (char **) sp, 0);
|
|
+ break;
|
|
+ case 'o':
|
|
+ vp->v_integer = strtoull(s, (char **) sp, 8);
|
|
+ break;
|
|
+ case 'u':
|
|
+ vp->v_integer = strtoull(s, (char **) sp, 10);
|
|
+ break;
|
|
+ case 'x':
|
|
+ case 'X':
|
|
+ vp->v_integer = strtoull(s, (char **) sp, 16);
|
|
+ break;
|
|
+ case 'p':
|
|
+ vp->v_pointer = (void *) strtoull(s, (char **) sp, 0);
|
|
+ break;
|
|
+ case 'f':
|
|
+ case 'g':
|
|
+ case 'e':
|
|
+ case 'E':
|
|
+ vp->v_double = strtold(s, (char **) sp);
|
|
+ break;
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int
|
|
+process_char_class(const char **fmt, const char **sp, int width)
|
|
+{
|
|
+ unsigned char *s, c, prev_char = 0;
|
|
+ unsigned char table[255];
|
|
+ int val = 1;
|
|
+
|
|
+ s = (unsigned char *) *fmt;
|
|
+ if (*s == '^') {
|
|
+ memset(table, 1, sizeof(table));
|
|
+ val = 0;
|
|
+ s++;
|
|
+ } else {
|
|
+ memset(table, 0, sizeof(table));
|
|
+ val = 1;
|
|
+ }
|
|
+ /* First character in set is closing bracket means add it to the
|
|
+ * set of characters */
|
|
+ if ((c = *s) == ']') {
|
|
+ table[c] = val;
|
|
+ prev_char = c;
|
|
+ s++;
|
|
+ }
|
|
+
|
|
+ /* Any other closing bracket finishes off the set */
|
|
+ while ((c = *s++) != ']') {
|
|
+ if (prev_char) {
|
|
+ if (c == '-' && *s != '\0' && *s != ']') {
|
|
+ c = *s++;
|
|
+ } else {
|
|
+ //table[prev_char] = val;
|
|
+ prev_char = '\0';
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (c == '\0')
|
|
+ return 0;
|
|
+
|
|
+ if (prev_char) {
|
|
+ while (prev_char < c)
|
|
+ table[prev_char++] = val;
|
|
+ }
|
|
+ table[c] = val;
|
|
+ prev_char = c;
|
|
+ }
|
|
+ *fmt = (char *) s;
|
|
+
|
|
+#if 0
|
|
+ {
|
|
+ int n;
|
|
+
|
|
+ printf("char class=");
|
|
+ for (n = 0; n < 255; n++)
|
|
+ if (table[n])
|
|
+ printf(isprint(n)? "%c" : "\\%03o", n);
|
|
+ printf("\n");
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ s = (unsigned char *) *sp;
|
|
+ while ((c = *s) != '\0' && table[c] && width--)
|
|
+ s++;
|
|
+
|
|
+ *sp = (char *) s;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+#ifdef TEST
|
|
+static int verify(const char *fmt, const char *s);
|
|
+static int verify_s(const char *fmt, const char *s);
|
|
+
|
|
+enum { S, I, L, F, D, P };
|
|
+
|
|
+int
|
|
+main(int argc, char **argv)
|
|
+{
|
|
+ verify("%d %d", "12 13");
|
|
+ verify("%d-%d", "12 13");
|
|
+ verify("%d-%d", "12-13");
|
|
+ verify("%u %u", "12 13");
|
|
+ verify("%o %o", "12 13");
|
|
+ verify("%x %x", "12 13");
|
|
+ verify("%X %X", "12 13");
|
|
+ verify("%hd %hd", "12 13");
|
|
+ verify("%ld %ld", "12 13");
|
|
+ verify("%lld %lld", "12 13");
|
|
+ verify("%Ld %Ld", "12 13");
|
|
+ verify("%qd %qd", "12 13");
|
|
+ verify("%f %f", "12 13");
|
|
+ verify("%lf %lf", "12 13");
|
|
+ verify("%Lf %Lf", "12 13");
|
|
+ verify("%qf %qf", "12 13");
|
|
+ verify("%*d-%d", "12-13");
|
|
+ verify("%*s %d", "12 13");
|
|
+ verify("%p", "0xdeadbeef");
|
|
+ verify("%*[a-e] %x", "deadbeef feeb");
|
|
+ verify("%*[a-f] %x", "deadbeef feeb");
|
|
+ verify("%*[^g-z] %x", "deadbeef feeb");
|
|
+ verify("%*[^ g-z] %x", "deadbeef feeb");
|
|
+ verify("%*[^ g-z-] %x", "dead-beef feeb");
|
|
+ verify("%*5s %d", "toast123 456");
|
|
+ verify("", "lalla");
|
|
+ verify("%u", "");
|
|
+
|
|
+ verify_s("%s", "aa bb");
|
|
+ verify_s("%s %s", "aa bb");
|
|
+ verify_s("%[a-z] %s", "aa bb");
|
|
+ verify_s("%c %s", "aa bb");
|
|
+ verify_s("%2c %s", " aa bb");
|
|
+ verify_s("%20c %s", " aa bb");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+verify(const char *fmt, const char *s)
|
|
+{
|
|
+ union scan_value vals[5], vals_ref[5], *v;
|
|
+ int n, m;
|
|
+
|
|
+ memset(vals, 0xe5, sizeof(vals));
|
|
+ memset(vals_ref, 0xe5, sizeof(vals_ref));
|
|
+
|
|
+ v = vals;
|
|
+ n = sec_sscanf(s, fmt, v + 0, v + 1, v + 2, v + 3, v + 4);
|
|
+
|
|
+ v = vals_ref;
|
|
+ m = sscanf(s, fmt, v + 0, v + 1, v + 2, v + 3, v + 4);
|
|
+
|
|
+ if (m != n) {
|
|
+ printf("FAILED: fmt=\"%s\"\n"
|
|
+ " str=\"%s\"\n"
|
|
+ " sec_scanf returns %d, sscanf returns %d\n",
|
|
+ fmt, s, n, m);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (memcmp(vals, vals_ref, sizeof(vals))) {
|
|
+ printf("FAILED: fmt=\"%s\"\n"
|
|
+ " str=\"%s\"\n"
|
|
+ " data differs!\n",
|
|
+ fmt, s);
|
|
+ printf("0x%Lx != 0x%Lx\n", vals[0].v_integer, vals_ref[0].v_integer);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int
|
|
+verify_s(const char *fmt, const char *s)
|
|
+{
|
|
+ char buf[3][256], buf_ref[3][256];
|
|
+ int n, m;
|
|
+
|
|
+ memset(buf, 0xe5, sizeof(buf));
|
|
+ memset(buf_ref, 0xe5, sizeof(buf_ref));
|
|
+
|
|
+ n = sec_sscanf(s, fmt, buf, sizeof(buf[0]), buf + 1, sizeof(buf[1]), buf + 2, sizeof(buf[2]));
|
|
+
|
|
+ m = sscanf(s, fmt, buf_ref, buf_ref + 1, buf_ref + 2);
|
|
+
|
|
+ if (m != n) {
|
|
+ printf("FAILED: fmt=\"%s\"\n"
|
|
+ " str=\"%s\"\n"
|
|
+ " sec_scanf returns %d, sscanf returns %d\n",
|
|
+ fmt, s, n, m);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (memcmp(buf, buf_ref, sizeof(buf))) {
|
|
+ printf("FAILED: fmt=\"%s\"\n"
|
|
+ " str=\"%s\"\n"
|
|
+ " data differs!\n",
|
|
+ fmt, s);
|
|
+ printf("%s != %s\n", buf[0], buf_ref[0]);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+#endif
|