Skip to content

Commit c6b3767

Browse files
Jim HsuChAoSUnItY
authored andcommitted
feat: Add snprintf
This patch adds snprintf. The second parameter "size" is expected to accept only zero or positive integer, otherwise as C11 specification states, it would be undefined behavior.
1 parent 6196ab1 commit c6b3767

File tree

9 files changed

+109
-14
lines changed

9 files changed

+109
-14
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ bootstrap: $(OUT)/$(STAGE2)
121121
fi
122122

123123
$(BUILD_SESSION):
124-
$(PRINTF) "ARCH=$(ARCH)" > $@
124+
$(VECHO) "ARCH=$(ARCH)" > $@
125125

126126
.PHONY: clean
127127
clean:

lib/c.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,3 +713,72 @@ void free(void *ptr)
713713
__freelist_head->prev = cur;
714714
__freelist_head = cur;
715715
}
716+
717+
void snprintf(char *buffer, int n, char *str, ...)
718+
{
719+
int *var_args = &str + 4;
720+
int si = 0, bi = 0, pi = 0;
721+
722+
if (n == 0)
723+
return;
724+
725+
while (str[si]) {
726+
if (bi >= n - 1) {
727+
break;
728+
} else if (str[si] != '%') {
729+
buffer[bi] = str[si];
730+
bi++;
731+
si++;
732+
} else {
733+
int w = 0, zp = 0, pp = 0;
734+
735+
si++;
736+
if (str[si] == '#') {
737+
pp = 1;
738+
si++;
739+
}
740+
if (str[si] == '0') {
741+
zp = 1;
742+
si++;
743+
}
744+
if (str[si] >= '1' && str[si] <= '9') {
745+
w = str[si] - '0';
746+
si++;
747+
if (str[si] >= '0' && str[si] <= '9') {
748+
w = w * 10;
749+
w += str[si] - '0';
750+
si++;
751+
}
752+
}
753+
switch (str[si]) {
754+
case 37: /* % */
755+
buffer[bi++] = '%';
756+
si++;
757+
continue;
758+
case 99: /* c */
759+
buffer[bi++] = var_args[pi];
760+
break;
761+
case 115: /* s */
762+
strcpy(buffer + bi, var_args[pi]);
763+
bi += strlen(var_args[pi]);
764+
break;
765+
case 111: /* o */
766+
bi += __format(buffer + bi, var_args[pi], w, zp, 8, pp);
767+
break;
768+
case 100: /* d */
769+
bi += __format(buffer + bi, var_args[pi], w, zp, 10, 0);
770+
break;
771+
case 120: /* x */
772+
bi += __format(buffer + bi, var_args[pi], w, zp, 16, pp);
773+
break;
774+
default:
775+
abort();
776+
break;
777+
}
778+
pi++;
779+
si++;
780+
}
781+
}
782+
783+
buffer[n - 1] = 0;
784+
}

src/defs.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@
1717
#define MAX_VAR_LEN 32
1818
#define MAX_TYPE_LEN 32
1919
#define MAX_PARAMS 8
20-
#define MAX_LOCALS 1500
20+
#define MAX_LOCALS 1600
2121
#define MAX_FIELDS 64
2222
#define MAX_FUNCS 512
2323
#define MAX_TYPES 64
24-
#define MAX_IR_INSTR 50000
24+
#define MAX_IR_INSTR 60000
2525
#define MAX_BB_PRED 128
2626
#define MAX_BB_DOM_SUCC 64
2727
#define MAX_BB_RDOM_SUCC 256
2828
#define MAX_GLOBAL_IR 256
2929
#define MAX_LABEL 4096
30-
#define MAX_SOURCE 327680
30+
#define MAX_SOURCE 524288
3131
#define MAX_CODE 262144
3232
#define MAX_DATA 262144
3333
#define MAX_SYMTAB 65536

src/parser.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3401,17 +3401,15 @@ void load_source_file(char *file)
34013401
}
34023402
if (!strncmp(buffer, "#include ", 9) && (buffer[9] == '"')) {
34033403
char path[MAX_LINE_LEN];
3404-
int c = strlen(file) - 1;
3404+
int c = strlen(file) - 1, inclusion_path_len = strlen(buffer) - 11;
34053405
while (c > 0 && file[c] != '/')
34063406
c--;
34073407
if (c) {
34083408
/* prepend directory name */
3409-
strncpy(path, file, c + 1);
3410-
c++;
3409+
snprintf(path, c + 2, "%s", file);
34113410
}
3412-
path[c] = 0;
3413-
buffer[strlen(buffer) - 2] = 0;
3414-
strcpy(path + c, buffer + 10);
3411+
3412+
snprintf(path + c + 1, inclusion_path_len, "%s", buffer + 10);
34153413
load_source_file(path);
34163414
} else {
34173415
strcpy(SOURCE + source_idx, buffer);

tests/driver.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,4 +1611,32 @@ int main()
16111611
}
16121612
EOF
16131613

1614+
# snprintf, including truncation and zero size input
1615+
try_output 0 "Hello World 1123" << EOF
1616+
int main() {
1617+
char buffer[50];
1618+
snprintf(buffer, 50, "Hello %s %d", "World", 1123);
1619+
printf("%s", buffer);
1620+
return 0;
1621+
}
1622+
EOF
1623+
1624+
try_output 0 "" << EOF
1625+
int main() {
1626+
char buffer[20];
1627+
snprintf(buffer, 0, "Number: %d", -37);
1628+
printf("%s", buffer);
1629+
return 0;
1630+
}
1631+
EOF
1632+
1633+
try_output 0 "Number: -" << EOF
1634+
int main() {
1635+
char buffer[10];
1636+
snprintf(buffer, 10, "Number: %d", -37);
1637+
printf("%s", buffer);
1638+
return 0;
1639+
}
1640+
EOF
1641+
16141642
echo OK

tests/snapshots/fib-arm.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tests/snapshots/fib-riscv.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tests/snapshots/hello-arm.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tests/snapshots/hello-riscv.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)