forked from openkylin/safeclib
96 lines
2.8 KiB
C
96 lines
2.8 KiB
C
EXPORT int sscanf_s(const char *restrict buffer, const char *restrict fmt, ...) {
|
|
va_list ap;
|
|
int ret;
|
|
#if defined(HAVE_STRSTR)
|
|
char *p;
|
|
#endif
|
|
const char *temp_fmt = fmt;
|
|
|
|
if (unlikely(buffer == NULL)) {
|
|
invoke_safe_str_constraint_handler("sscanf_s: buffer is null", NULL, ESNULLP);
|
|
errno = ESNULLP;
|
|
return EOF;
|
|
}
|
|
|
|
if (unlikely(fmt == NULL)) {
|
|
invoke_safe_str_constraint_handler("sscanf_s: fmt is null", NULL, ESNULLP);
|
|
errno = ESNULLP;
|
|
return EOF;
|
|
}
|
|
|
|
#if defined(HAVE_STRSTR)
|
|
if (unlikely((p = strstr((char *)fmt, "%n")))) {
|
|
if ((p - fmt == 0) || *(p - 1) != '%') {
|
|
invoke_safe_str_constraint_handler("sscanf_s: illegal %n", NULL, EINVAL);
|
|
errno = EINVAL;
|
|
return EOF;
|
|
}
|
|
}
|
|
#elif defined(HAVE_STRCHR)
|
|
/* Assuming 'flen' is the length of 'fmt' */
|
|
size_t flen = strlen(fmt);
|
|
if (unlikely((p = strchr(fmt, flen, 'n')))) {
|
|
if (((p - fmt >= 1) && *(p - 1) == '%') && ((p - fmt == 1) || *(p - 2) != '%')) {
|
|
invoke_safe_str_constraint_handler("sscanf_s: illegal %n", NULL, EINVAL);
|
|
errno = EINVAL;
|
|
return EOF;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
va_start(ap, fmt);
|
|
while (*temp_fmt) {
|
|
if (*temp_fmt == '%') {
|
|
temp_fmt++;
|
|
|
|
if (*temp_fmt == 's') {
|
|
char *buf = va_arg(ap, char*);
|
|
rsize_t bufsize = va_arg(ap, rsize_t);
|
|
if (!buf || bufsize > RSIZE_MAX) {
|
|
va_end(ap);
|
|
invoke_safe_str_constraint_handler("sscanf_s: buffer error", NULL, EINVAL);
|
|
errno = EINVAL;
|
|
return EOF;
|
|
}
|
|
temp_fmt++;
|
|
} else if (*temp_fmt == 'c' || *temp_fmt == '[') {
|
|
char *buf = va_arg(ap, char*);
|
|
rsize_t bufsize = va_arg(ap, rsize_t);
|
|
if (bufsize != 1) {
|
|
va_end(ap);
|
|
invoke_safe_str_constraint_handler("sscanf_s: buffer size error", NULL, EINVAL);
|
|
errno = EINVAL;
|
|
return EOF;
|
|
}
|
|
temp_fmt++;
|
|
} else {
|
|
temp_fmt++;
|
|
}
|
|
} else {
|
|
temp_fmt++;
|
|
}
|
|
}
|
|
va_end(ap);
|
|
|
|
va_start(ap, fmt);
|
|
ret = vsscanf(buffer, fmt, ap);
|
|
va_end(ap);
|
|
|
|
if (unlikely(ret < 0)) {
|
|
char errstr[128] = "sscanf_s: ";
|
|
strcat(errstr, strerror(errno));
|
|
invoke_safe_str_constraint_handler(errstr, NULL, errno);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void test_sscanf_s() {
|
|
const char *input = "cherry 789";
|
|
char buf[10];
|
|
int num;
|
|
assert(sscanf_s(input, "%9s %d", buf, sizeof(buf), &num) == 2);
|
|
assert(strcmp(buf, "cherry") == 0);
|
|
assert(num == 789);
|
|
}
|