diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index 85e5690..464673e 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -141,7 +141,8 @@ sw buf_parse_array (s_buf *buf, s_array *dest)
errx(1, "buf_parse_array: parse_data: dimension mismatch");
return -1;
}
- while (i == tmp.dimension - 1) {
+ while (i == tmp.dimension - 1 &&
+ address[i] < tmp.dimensions[i].count) {
if ((r = parse(buf, item)) <= 0)
goto restore;
result += r;
@@ -670,6 +671,35 @@ sw buf_parse_comments (s_buf *buf)
return r;
}
+sw buf_parse_digit (s_buf *buf, const s_str *bases, uw bases_count,
+ u8 *dest)
+{
+ character c;
+ sw digit;
+ uw i = 0;
+ sw r;
+ assert(buf);
+ assert(bases);
+ assert(bases_count);
+ if ((r = buf_peek_character_utf8(buf, &c)) <= 0)
+ return r;
+ while (i < bases_count) {
+ if ((digit = str_character_position(bases + i, c)) >= 0) {
+ if (digit > 255) {
+ assert(! "buf_parse_digit: digit overflow");
+ errx(1, "buf_parse_digit: digit overflow: %ld", digit);
+ return -1;
+ }
+ if ((r = buf_read_character_utf8(buf, &c)) <= 0)
+ return r;
+ *dest = digit;
+ return r;
+ }
+ i++;
+ }
+ return 0;
+}
+
sw buf_parse_digit_hex (s_buf *buf, u8 *dest)
{
character c;
@@ -690,26 +720,6 @@ sw buf_parse_digit_hex (s_buf *buf, u8 *dest)
return r;
}
-sw buf_parse_digit (s_buf *buf, const s_str *bases, uw bases_count)
-{
- character c;
- sw digit;
- uw i = 0;
- sw r;
- assert(buf);
- assert(bases);
- assert(bases_count);
- if ((r = buf_peek_character_utf8(buf, &c)) <= 0)
- return r;
- while (i < bases_count &&
- (digit = str_character_position(bases + i, c)) < 0)
- i++;
- if (digit >= 0)
- if ((r = buf_read_character_utf8(buf, &c)) <= 0)
- return r;
- return digit;
-}
-
sw buf_parse_digit_oct (s_buf *buf, u8 *dest)
{
character c;
@@ -1566,7 +1576,9 @@ sw buf_parse_s (s_buf *buf, u8 size, void *dest)
sw buf_parse_s_bases (s_buf *buf, const s_str *bases, uw bases_count,
bool negative, u8 size, void *dest)
{
+ u8 digit;
sw r;
+ sw radix;
sw result = 0;
s_buf_save save;
s64 tmp = 0;
@@ -1577,23 +1589,34 @@ sw buf_parse_s_bases (s_buf *buf, const s_str *bases, uw bases_count,
assert(size <= 8);
assert(dest);
if (size > 8) {
+ assert(! "buf_parse_s_bases: unsupported integer size");
errx(1, "buf_parse_s_bases: unsupported integer size: %u", size);
return -1;
}
buf_save_init(buf, &save);
- while ((r = buf_parse_digit(buf, bases, bases_count)) >= 0) {
+ if ((radix = str_length_utf8(bases)) < 2) {
+ assert(! "buf_parse_s_bases: invalid radix");
+ errx(1, "buf_parse_s_bases: invalid radix: %ld", radix);
+ return -1;
+ }
+ while ((r = buf_parse_digit(buf, bases, bases_count, &digit)) > 0) {
result += r;
+ if (digit >= radix) {
+ assert(! "buf_parse_s_bases: digit not in radix");
+ errx(1, "buf_parse_s_bases: digit not in radix: %u", digit);
+ return -1;
+ }
if (tmp > ((((s64) 1 << (size * 8 - 1)) - 1) +
- (s64) bases[0].size - 1) / (s64) bases[0].size) {
+ (s64) radix - 1) / (s64) radix) {
warnx("buf_parse_s_bases: integer overflow");
goto restore;
}
- tmp *= bases[0].size;
- if (tmp > (s64) (1 << (size * 8 - 1)) - 1 - r) {
+ tmp *= radix;
+ if (tmp > (s64) (1 << (size * 8 - 1)) - 1 - digit) {
warnx("buf_parse_s_bases: integer overflow");
goto restore;
}
- tmp += r;
+ tmp += digit;
}
if (negative)
tmp = -tmp;
@@ -2212,8 +2235,8 @@ sw buf_parse_u (s_buf *buf, u8 size, void *dest)
buf_save_init(buf, &save);
if ((r = buf_read_1(buf, "0b")) < 0)
goto restore;
- result += r;
if (r > 0) {
+ result += r;
if ((r = buf_parse_u_bases(buf, bases_bin, 1, size,
dest)) <= 0)
goto restore;
@@ -2257,7 +2280,9 @@ sw buf_parse_u (s_buf *buf, u8 size, void *dest)
sw buf_parse_u_bases (s_buf *buf, const s_str *bases, uw bases_count,
u8 size, void *dest)
{
+ u8 digit;
sw r;
+ sw radix;
sw result = 0;
s_buf_save save;
u64 tmp = 0;
@@ -2268,23 +2293,34 @@ sw buf_parse_u_bases (s_buf *buf, const s_str *bases, uw bases_count,
assert(size <= 8);
assert(dest);
if (size > 8) {
+ assert(! "buf_parse_u_bases: unsupported integer size");
errx(1, "buf_parse_u_bases: unsupported integer size: %u", size);
return -1;
}
buf_save_init(buf, &save);
- while ((r = buf_parse_digit(buf, bases, bases_count)) >= 0) {
+ if ((radix = str_length_utf8(bases)) < 2) {
+ assert(! "buf_parse_u_bases: invalid radix");
+ errx(1, "buf_parse_u_bases: invalid radix: %ld", radix);
+ return -1;
+ }
+ while ((r = buf_parse_digit(buf, bases, bases_count, &digit)) > 0) {
result += r;
+ if (digit >= radix) {
+ assert(! "buf_parse_u_bases: digit not in radix");
+ errx(1, "buf_parse_u_bases: digit not in radix: %u", digit);
+ return -1;
+ }
if (tmp > ((((u64) 1 << (size * 8)) - 1) +
- (u64) bases[0].size - 1) / (u64) bases[0].size) {
+ (u64) radix - 1) / (u64) radix) {
warnx("buf_parse_u_bases: integer overflow");
goto restore;
}
- tmp *= bases[0].size;
- if (tmp > (u64) (1 << (size * 8)) - 1 - r) {
+ tmp *= radix;
+ if (tmp > (u64) (1 << (size * 8)) - 1 - digit) {
warnx("buf_parse_u_bases: integer overflow");
goto restore;
}
- tmp += r;
+ tmp += digit;
}
memcpy(dest, &tmp + 8 - size, size);
r = result;
diff --git a/libc3/buf_parse.h b/libc3/buf_parse.h
index f3aba89..e988173 100644
--- a/libc3/buf_parse.h
+++ b/libc3/buf_parse.h
@@ -39,7 +39,8 @@ sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, u8 min_precedence);
sw buf_parse_cfn (s_buf *buf, s_cfn *dest);
sw buf_parse_character (s_buf *buf, character *dest);
sw buf_parse_comments (s_buf *buf);
-sw buf_parse_digit (s_buf *buf, const s_str *bases, uw bases_count);
+sw buf_parse_digit (s_buf *buf, const s_str *bases, uw bases_count,
+ u8 *dest);
sw buf_parse_digit_bin (s_buf *buf, u8 *dest);
sw buf_parse_digit_hex (s_buf *buf, u8 *dest);
sw buf_parse_digit_oct (s_buf *buf, u8 *dest);
diff --git a/libc3/env.c b/libc3/env.c
index 005afc5..07cde98 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -389,7 +389,8 @@ bool env_eval_ident (s_env *env, const s_ident *ident, s_tag *dest)
assert(ident);
if (! (tag = frame_get(env->frame, ident->sym))) {
assert(! "env_eval_ident: unbound variable");
- errx(1, "env_eval_ident: unbound variable");
+ errx(1, "env_eval_ident: %s: unbound variable",
+ ident->sym->str.ptr.ps8);
}
tag_copy(tag, dest);
return true;
diff --git a/libc3/str.c b/libc3/str.c
index f5abc18..a476623 100644
--- a/libc3/str.c
+++ b/libc3/str.c
@@ -33,7 +33,7 @@ e_bool str_character_is_reserved (character c)
sw str_character_position (const s_str *str, character c)
{
uw i = 0;
- sw r;
+ sw r = 0;
s_str tmp;
character tmp_c;
assert(str);
@@ -188,6 +188,20 @@ s_str * str_inspect (const s_str *src, s_str *dest)
return buf_to_str(&buf, dest);
}
+sw str_length_utf8 (const s_str *str)
+{
+ character c;
+ sw r;
+ sw result = 0;
+ s_str tmp;
+ tmp = *str;
+ while ((r = str_read_character_utf8(&tmp, &c)) > 0)
+ result++;
+ if (r < 0)
+ return r;
+ return result;
+}
+
s_str * str_new (s8 *free, uw size, const s8 *p)
{
s_str *str;
diff --git a/libc3/str.h b/libc3/str.h
index d99013e..5196589 100644
--- a/libc3/str.h
+++ b/libc3/str.h
@@ -57,6 +57,7 @@ sw str_character_position (const s_str *str, character c);
s_str * str_copy (const s_str *src, s_str *dest);
e_bool str_has_reserved_characters (const s_str *str);
s_str * str_inspect (const s_str *x, s_str *dest);
+sw str_length_utf8 (const s_str *str);
sw str_peek_bool (const s_str *src, bool *p);
sw str_peek_character (const s_str *src, character *p);
sw str_peek_f32 (const s_str *src, f32 *p);
diff --git a/test/buf_parse_test.c b/test/buf_parse_test.c
index 9eed050..3d44cc0 100644
--- a/test/buf_parse_test.c
+++ b/test/buf_parse_test.c
@@ -470,6 +470,7 @@
TEST_EQ(buf_parse_str(&buf, &dest), 0); \
TEST_EQ(buf.rpos, 0); \
buf_clean(&buf); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_NOT_STR_U8(test) \
@@ -482,6 +483,7 @@
TEST_EQ(buf.rpos, 0); \
TEST_EQ(dest, 0); \
buf_clean(&buf); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_NOT_SYM(test) \
@@ -493,6 +495,7 @@
TEST_EQ(buf_parse_sym(&buf, &dest), 0); \
TEST_EQ(buf.rpos, 0); \
buf_clean(&buf); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_STR(test, expected) \
@@ -509,6 +512,7 @@
TEST_STRNCMP(dest.ptr.p, (expected), dest.size); \
buf_clean(&buf); \
str_clean(&dest); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_STR_EOF(test) \
@@ -521,6 +525,7 @@
TEST_EQ(buf_parse_str(&buf, &dest), -1); \
TEST_EQ(buf.rpos, 0); \
buf_clean(&buf); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_STR_CHARACTER(test, expected) \
@@ -532,6 +537,7 @@
TEST_EQ(buf_parse_str_character(&buf, &dest), strlen(test)); \
TEST_EQ(dest, (expected)); \
buf_clean(&buf); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_STR_N(test, n, expected) \
@@ -547,6 +553,7 @@
TEST_EQ(memcmp(dest.ptr.p, expected, n), 0); \
buf_clean(&buf); \
str_clean(&dest); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_STR_U8(test, size, expected) \
@@ -559,6 +566,7 @@
TEST_EQ(buf.rpos, (size)); \
TEST_EQ(dest, (expected)); \
buf_clean(&buf); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_STR_U8_EOF(test) \
@@ -571,6 +579,7 @@
TEST_EQ(buf.rpos, 0); \
TEST_EQ(dest, 0x80); \
buf_clean(&buf); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_SYM(test, expected) \
@@ -587,6 +596,7 @@
if (g_test_last_ok) \
TEST_STRNCMP(dest->str.ptr.p, (expected), dest->str.size); \
buf_clean(&buf); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_SYM_EOF(test) \
@@ -598,6 +608,7 @@
TEST_EQ(buf_parse_sym(&buf, &dest), -1); \
TEST_EQ(buf.rpos, 0); \
buf_clean(&buf); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_TAG(test) \
@@ -610,6 +621,7 @@
TEST_EQ(buf_parse_tag(&buf, &dest), strlen(test)); \
buf_clean(&buf); \
tag_clean(&dest); \
+ test_context(NULL); \
} while (0)
#define BUF_PARSE_TEST_TUPLE(test) \
@@ -622,6 +634,18 @@
TEST_EQ(buf_parse_tuple(&buf, &dest), strlen(test)); \
buf_clean(&buf); \
tuple_clean(&dest); \
+ test_context(NULL); \
+ } while (0)
+
+#define BUF_PARSE_TEST_U8(test, expected) \
+ do { \
+ s_buf buf; \
+ u8 u; \
+ test_context("buf_parse_u8(" # test ")"); \
+ buf_init_1(&buf, (test)); \
+ TEST_EQ(buf_parse_u8(&buf, &u), strlen(test)); \
+ TEST_EQ(u, (expected)); \
+ test_context(NULL); \
} while (0)
void buf_parse_test_bool ();
@@ -649,6 +673,7 @@ void buf_parse_test_str_u8 ();
void buf_parse_test_sym ();
void buf_parse_test_tag ();
void buf_parse_test_tuple ();
+void buf_parse_test_u8 ();
void buf_parse_test ()
{
@@ -675,6 +700,7 @@ void buf_parse_test ()
buf_parse_test_list();
buf_parse_test_tag();
buf_parse_test_tuple();
+ buf_parse_test_u8();
buf_parse_test_ident();
buf_parse_test_cfn();
}
@@ -1228,3 +1254,69 @@ void buf_parse_test_tuple ()
BUF_PARSE_TEST_TUPLE("{{a, b}, c}");
BUF_PARSE_TEST_TUPLE("{{a, b}, {c, d}}");
}
+
+void buf_parse_test_u8 ()
+{
+ BUF_PARSE_TEST_U8("0b0", 0);
+ BUF_PARSE_TEST_U8("0b1", 1);
+ BUF_PARSE_TEST_U8("0b00", 0);
+ BUF_PARSE_TEST_U8("0b01", 1);
+ BUF_PARSE_TEST_U8("0b10", 2);
+ BUF_PARSE_TEST_U8("0b11", 3);
+ BUF_PARSE_TEST_U8("0b000", 0);
+ BUF_PARSE_TEST_U8("0b001", 1);
+ BUF_PARSE_TEST_U8("0b010", 2);
+ BUF_PARSE_TEST_U8("0b011", 3);
+ BUF_PARSE_TEST_U8("0b100", 4);
+ BUF_PARSE_TEST_U8("0b101", 5);
+ BUF_PARSE_TEST_U8("0b110", 6);
+ BUF_PARSE_TEST_U8("0b111", 7);
+ BUF_PARSE_TEST_U8("0o0", 0);
+ BUF_PARSE_TEST_U8("0o1", 1);
+ BUF_PARSE_TEST_U8("0o2", 2);
+ BUF_PARSE_TEST_U8("0o3", 3);
+ BUF_PARSE_TEST_U8("0o4", 4);
+ BUF_PARSE_TEST_U8("0o5", 5);
+ BUF_PARSE_TEST_U8("0o6", 6);
+ BUF_PARSE_TEST_U8("0o7", 7);
+ BUF_PARSE_TEST_U8("0o00", 0);
+ BUF_PARSE_TEST_U8("0o01", 1);
+ BUF_PARSE_TEST_U8("0o10", 8);
+ BUF_PARSE_TEST_U8("0o11", 9);
+ BUF_PARSE_TEST_U8("0o000", 0);
+ BUF_PARSE_TEST_U8("0x0", 0);
+ BUF_PARSE_TEST_U8("0x1", 1);
+ BUF_PARSE_TEST_U8("0x2", 2);
+ BUF_PARSE_TEST_U8("0x3", 2);
+ BUF_PARSE_TEST_U8("0x4", 2);
+ BUF_PARSE_TEST_U8("0x5", 2);
+ BUF_PARSE_TEST_U8("0x6", 2);
+ BUF_PARSE_TEST_U8("0x7", 2);
+ BUF_PARSE_TEST_U8("0x8", 2);
+ BUF_PARSE_TEST_U8("0x9", 2);
+ BUF_PARSE_TEST_U8("0xA", 2);
+ BUF_PARSE_TEST_U8("0xB", 2);
+ BUF_PARSE_TEST_U8("0xC", 2);
+ BUF_PARSE_TEST_U8("0xD", 2);
+ BUF_PARSE_TEST_U8("0xE", 2);
+ BUF_PARSE_TEST_U8("0xF", 2);
+ BUF_PARSE_TEST_U8("0x00", 0);
+ BUF_PARSE_TEST_U8("0x01", 1);
+ BUF_PARSE_TEST_U8("0x10", 16);
+ BUF_PARSE_TEST_U8("0x11", 17);
+ BUF_PARSE_TEST_U8("0x000", 0);
+ BUF_PARSE_TEST_U8("0", 0);
+ BUF_PARSE_TEST_U8("1", 1);
+ BUF_PARSE_TEST_U8("2", 2);
+ BUF_PARSE_TEST_U8("3", 3);
+ BUF_PARSE_TEST_U8("4", 4);
+ BUF_PARSE_TEST_U8("5", 5);
+ BUF_PARSE_TEST_U8("6", 6);
+ BUF_PARSE_TEST_U8("7", 7);
+ BUF_PARSE_TEST_U8("8", 8);
+ BUF_PARSE_TEST_U8("9", 9);
+ BUF_PARSE_TEST_U8("00", 0);
+ BUF_PARSE_TEST_U8("10", 10);
+ BUF_PARSE_TEST_U8("11", 11);
+ BUF_PARSE_TEST_U8("000", 0);
+}
diff --git a/test/cfn_test.c b/test/cfn_test.c
index e66df12..354e804 100644
--- a/test/cfn_test.c
+++ b/test/cfn_test.c
@@ -42,6 +42,7 @@ void cfn_test_apply ()
{
s_cfn tmp;
cfn_init(&tmp);
+
cfn_clean(&tmp);
}
@@ -55,6 +56,10 @@ void cfn_test_copy ()
void cfn_test_link ()
{
+ s_cfn tmp;
+ cfn_init(&tmp);
+ tmp.name
+ cfn_clean(&tmp);
}
void cfn_test_set_type ()