Skip to content

Commit e3350d2

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 a603970 commit e3350d2

File tree

9 files changed

+110
-15
lines changed

9 files changed

+110
-15
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
@@ -728,3 +728,72 @@ void free(void *ptr)
728728
__freelist_head->prev = cur;
729729
__freelist_head = cur;
730730
}
731+
732+
void snprintf(char *buffer, int n, char *str, ...)
733+
{
734+
int *var_args = &str + 4;
735+
int si = 0, bi = 0, pi = 0;
736+
737+
if (n == 0)
738+
return;
739+
740+
while (str[si]) {
741+
if (bi >= n - 1) {
742+
break;
743+
} else if (str[si] != '%') {
744+
buffer[bi] = str[si];
745+
bi++;
746+
si++;
747+
} else {
748+
int w = 0, zp = 0, pp = 0;
749+
750+
si++;
751+
if (str[si] == '#') {
752+
pp = 1;
753+
si++;
754+
}
755+
if (str[si] == '0') {
756+
zp = 1;
757+
si++;
758+
}
759+
if (str[si] >= '1' && str[si] <= '9') {
760+
w = str[si] - '0';
761+
si++;
762+
if (str[si] >= '0' && str[si] <= '9') {
763+
w = w * 10;
764+
w += str[si] - '0';
765+
si++;
766+
}
767+
}
768+
switch (str[si]) {
769+
case 37: /* % */
770+
buffer[bi++] = '%';
771+
si++;
772+
continue;
773+
case 99: /* c */
774+
buffer[bi++] = var_args[pi];
775+
break;
776+
case 115: /* s */
777+
strcpy(buffer + bi, var_args[pi]);
778+
bi += strlen(var_args[pi]);
779+
break;
780+
case 111: /* o */
781+
bi += __format(buffer + bi, var_args[pi], w, zp, 8, pp);
782+
break;
783+
case 100: /* d */
784+
bi += __format(buffer + bi, var_args[pi], w, zp, 10, 0);
785+
break;
786+
case 120: /* x */
787+
bi += __format(buffer + bi, var_args[pi], w, zp, 16, pp);
788+
break;
789+
default:
790+
abort();
791+
break;
792+
}
793+
pi++;
794+
si++;
795+
}
796+
}
797+
798+
buffer[n - 1] = 0;
799+
}

src/defs.h

Lines changed: 4 additions & 4 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
@@ -39,7 +39,7 @@
3939
#define MAX_CASES 128
4040
#define MAX_NESTING 128
4141
#define MAX_OPERAND_STACK_SIZE 32
42-
#define MAX_ANALYSIS_STACK_SIZE 750
42+
#define MAX_ANALYSIS_STACK_SIZE 800
4343

4444
/* Default capacities for common data structures */
4545
/* Default arena size is initialized with 256 KiB */

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)