Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 49 additions & 85 deletions lib/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#define true 1
#define false 0

#define INT_MAX 0x7fffffff
#define INT_MIN 0x80000000

#if defined(__arm__)
#define __SIZEOF_POINTER__ 4
#define __syscall_exit 1
Expand Down Expand Up @@ -288,60 +291,65 @@ int __format(char *buffer,
return bi;
}

void printf(char *str, ...)
int __format_to_buf(char *buffer, char *format, int *var_args, int size)
{
int *var_args = &str + 4;
char buffer[200];
int si = 0, bi = 0, pi = 0;

while (str[si]) {
if (str[si] != '%') {
buffer[bi] = str[si];
if (size == 0)
return 0;

while (format[si] && bi < size - 1) {
if (format[si] != '%') {
buffer[bi] = format[si];
bi++;
si++;
} else {
int w = 0, zp = 0, pp = 0;
int w = 0, zp = 0, pp = 0, v = var_args[pi], l;

si++;
if (str[si] == '#') {
if (format[si] == '#') {
pp = 1;
si++;
}
if (str[si] == '0') {
if (format[si] == '0') {
zp = 1;
si++;
}
if (str[si] >= '1' && str[si] <= '9') {
w = str[si] - '0';
if (format[si] >= '1' && format[si] <= '9') {
w = format[si] - '0';
si++;
while (str[si] >= '0' && str[si] <= '9') {
while (format[si] >= '0' && format[si] <= '9') {
w *= 10;
w += str[si] - '0';
w += format[si] - '0';
si++;
}
}
if (str[si] == 's') {
switch (format[si]) {
case 's':
/* append param pi as string */
int l = strlen(var_args[pi]);
strcpy(buffer + bi, var_args[pi]);
l = strlen(v);
l = l < size - bi ? l : size - bi;
strncpy(buffer + bi, v, l);
bi += l;
} else if (str[si] == 'c') {
break;
case 'c':
/* append param pi as char */
buffer[bi] = var_args[pi];
buffer[bi] = v;
bi += 1;
} else if (str[si] == 'o') {
break;
case 'o':
/* append param as octal */
int v = var_args[pi];
bi += __format(buffer + bi, v, w, zp, 8, pp);
} else if (str[si] == 'd') {
break;
case 'd':
/* append param as decimal */
int v = var_args[pi];
bi += __format(buffer + bi, v, w, zp, 10, 0);
} else if (str[si] == 'x') {
break;
case 'x':
/* append param as hex */
int v = var_args[pi];
bi += __format(buffer + bi, v, w, zp, 16, pp);
} else if (str[si] == '%') {
break;
case '%':
/* append literal '%' character */
buffer[bi] = '%';
bi++;
Expand All @@ -352,71 +360,27 @@ void printf(char *str, ...)
si++;
}
}
buffer[bi] = 0;
__syscall(__syscall_write, 1, buffer, bi);

int len = size - 1 > bi ? bi : size - 1;
buffer[len] = 0;
return len;
}

void sprintf(char *buffer, char *str, ...)
int printf(char *str, ...)
{
int *var_args = &str + 4;
int si = 0, bi = 0, pi = 0;
char buffer[200];
int len = __format_to_buf(buffer, str, &str + 4, INT_MAX);
return __syscall(__syscall_write, 1, buffer, len);
}

while (str[si]) {
if (str[si] != '%') {
buffer[bi] = str[si];
bi++;
si++;
} else {
int w = 0, zp = 0, pp = 0;
int sprintf(char *buffer, char *str, ...)
{
return __format_to_buf(buffer, str, &str + 4, INT_MAX);
}

si++;
if (str[si] == '#') {
pp = 1;
si++;
}
if (str[si] == '0') {
zp = 1;
si++;
}
if (str[si] >= '1' && str[si] <= '9') {
w = str[si] - '0';
si++;
if (str[si] >= '0' && str[si] <= '9') {
w *= 10;
w += str[si] - '0';
si++;
}
}
switch (str[si]) {
case 37: /* % */
buffer[bi++] = '%';
si++;
continue;
case 99: /* c */
buffer[bi++] = var_args[pi];
break;
case 115: /* s */
strcpy(buffer + bi, var_args[pi]);
bi += strlen(var_args[pi]);
break;
case 111: /* o */
bi += __format(buffer + bi, var_args[pi], w, zp, 8, pp);
break;
case 100: /* d */
bi += __format(buffer + bi, var_args[pi], w, zp, 10, 0);
break;
case 120: /* x */
bi += __format(buffer + bi, var_args[pi], w, zp, 16, pp);
break;
default:
abort();
break;
}
pi++;
si++;
}
}
buffer[bi] = 0;
int snprintf(char *buffer, int n, char *str, ...)
{
return __format_to_buf(buffer, str, &str + 4, n);
}

int __free_all();
Expand Down
8 changes: 4 additions & 4 deletions src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
#define MAX_VAR_LEN 32
#define MAX_TYPE_LEN 32
#define MAX_PARAMS 8
#define MAX_LOCALS 1500
#define MAX_LOCALS 1600
#define MAX_FIELDS 64
#define MAX_FUNCS 512
#define MAX_TYPES 64
#define MAX_IR_INSTR 50000
#define MAX_IR_INSTR 60000
#define MAX_BB_PRED 128
#define MAX_BB_DOM_SUCC 64
#define MAX_BB_RDOM_SUCC 256
#define MAX_GLOBAL_IR 256
#define MAX_LABEL 4096
#define MAX_SOURCE 327680
#define MAX_SOURCE 524288
#define MAX_CODE 262144
#define MAX_DATA 262144
#define MAX_SYMTAB 65536
Expand All @@ -39,7 +39,7 @@
#define MAX_CASES 128
#define MAX_NESTING 128
#define MAX_OPERAND_STACK_SIZE 32
#define MAX_ANALYSIS_STACK_SIZE 750
#define MAX_ANALYSIS_STACK_SIZE 800

/* Default capacities for common data structures */
/* Default arena size is initialized with 256 KiB */
Expand Down
13 changes: 7 additions & 6 deletions src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2621,6 +2621,9 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
if (lex_peek(T_numeric, NULL)) {
case_val = read_numeric_constant(token_str);
lex_expect(T_numeric); /* already read it */
} else if (lex_peek(T_char, token)) {
case_val = token[0];
lex_expect(T_char);
} else {
constant_t *cd = find_constant(token_str);
case_val = cd->value;
Expand Down Expand Up @@ -3401,17 +3404,15 @@ void load_source_file(char *file)
}
if (!strncmp(buffer, "#include ", 9) && (buffer[9] == '"')) {
char path[MAX_LINE_LEN];
int c = strlen(file) - 1;
int c = strlen(file) - 1, inclusion_path_len = strlen(buffer) - 11;
while (c > 0 && file[c] != '/')
c--;
if (c) {
/* prepend directory name */
strncpy(path, file, c + 1);
c++;
snprintf(path, c + 2, "%s", file);
}
path[c] = 0;
buffer[strlen(buffer) - 2] = 0;
strcpy(path + c, buffer + 10);

snprintf(path + c + 1, inclusion_path_len, "%s", buffer + 10);
load_source_file(path);
} else {
strcpy(SOURCE + source_idx, buffer);
Expand Down
63 changes: 63 additions & 0 deletions tests/driver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1611,4 +1611,67 @@ int main()
}
EOF

# printf family, including truncation and zero size input
try_output 11 "Hello World" << EOF
int main() {
int written = printf("Hello World");
return written;
}
EOF

# tests printf returns EBADF (errno 9) when stdout is closed
try_output 1 "" << EOF
int main()
{
__syscall(__syscall_close, 1);
int written = printf("Hello\n");
return written == -9;
}
EOF

try_output 11 "Hello World" << EOF
int main() {
char buffer[50];
int written = sprintf(buffer, "Hello World");
printf("%s", buffer);
return written;
}
EOF

try_output 16 "Hello World 1123" << EOF
int main() {
char buffer[50];
int written = sprintf(buffer, "Hello %s %d", "World", 1123);
printf("%s", buffer);
return written;
}
EOF

try_output 16 "Hello World 1123" << EOF
int main() {
char buffer[50];
int written = snprintf(buffer, 50, "Hello %s %d", "World", 1123);
printf("%s", buffer);
return written;
}
EOF

try_output 0 "" << EOF
int main() {
char buffer[20];
int written = snprintf(buffer, 0, "Number: %d", -37);
printf("%s", buffer);
return written;
}
EOF

try_output 9 "Number: -" << EOF
int main() {
char buffer[10];
int written = snprintf(buffer, 10, "Number: %d", -37);
printf("%s", buffer);
return written;
}
EOF

echo OK
2 changes: 1 addition & 1 deletion tests/snapshots/fib-arm.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/snapshots/fib-riscv.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/snapshots/hello-arm.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/snapshots/hello-riscv.json

Large diffs are not rendered by default.