commit b7f1d4226cb5e5ba3e2852294e8ec2a52d21129a
parent 475e50fe3d81bb50983e6b122e7a3629967b6cd2
Author: Sebastian <sebastian@sebsite.pw>
Date: Wed, 13 Apr 2022 20:33:48 -0400
ascii: abort strcasecmp when non-ASCII encountered
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
3 files changed, 19 insertions(+), 39 deletions(-)
diff --git a/ascii/strcmp.ha b/ascii/strcmp.ha
@@ -5,25 +5,18 @@ use strings;
// Compares two strings by their ASCII sort order, treating all capital letters
// as their lowercase counterpart (i.e. a case-insensitive comparison is
-// performed). If either string is not entirely composed of ASCII characters,
-// void is returned. Otherwise, zero is returned if the strings are equal, a
-// negative value if a is less than b, or a positive value if a is greater than
-// b.
-export fn strcasecmp(a: str, b: str) (int | void) = {
+// performed). Zero is returned if the strings are equal, a negative value if a
+// is less than b, or a positive value if a is greater than b. Aborts if a
+// non-ASCII byte is encountered.
+export fn strcasecmp(a: str, b: str) int = {
let a = strings::iter(a), b = strings::iter(b);
for (true) {
let ra = match (strings::next(&a)) {
case void =>
match (strings::next(&b)) {
case void =>
- return 0;
+ break;
case rune =>
- for (true) match (strings::next(&b)) {
- case void =>
- break;
- case let r: rune =>
- if (!valid(r)) return;
- };
return -1;
};
case let r: rune =>
@@ -31,24 +24,17 @@ export fn strcasecmp(a: str, b: str) (int | void) = {
};
let rb = match (strings::next(&b)) {
case void =>
- for (true) match (strings::next(&a)) {
- case void =>
- break;
- case let r: rune =>
- if (!valid(r)) return;
- };
return 1;
case let r: rune =>
yield r;
};
- if (!valid(ra) || !valid(rb)) {
- return;
- };
+ assert(valid(ra) && valid(rb));
let ra = tolower(ra), rb = tolower(rb);
if (ra != rb) {
return ra: u32: int - rb: u32: int;
};
};
+ return 0;
};
@test fn strcmp() void = {
diff --git a/format/xml/parser.ha b/format/xml/parser.ha
@@ -467,13 +467,11 @@ fn prolog(par: *parser) (void | error) = {
return par.line: syntaxerr;
};
// XXX: Deliberate omission: all values other than utf-8
- match (ascii::strcasecmp(attr.1, "utf-8")) {
- case void =>
+ if (!ascii::validstr(attr.1)) {
+ return utf8::invalid;
+ };
+ if (ascii::strcasecmp(attr.1, "utf-8") != 0) {
return utf8::invalid;
- case let n: int =>
- if (n != 0) {
- return utf8::invalid;
- };
};
};
@@ -491,13 +489,11 @@ fn prolog(par: *parser) (void | error) = {
return par.line: syntaxerr;
};
// XXX: Deliberate omission: non-standalone documents
- match (ascii::strcasecmp(attr.1, "yes")) {
- case void =>
+ if (!ascii::validstr(attr.1)) {
+ return par.line: syntaxerr;
+ };
+ if (ascii::strcasecmp(attr.1, "yes") != 0) {
return par.line: syntaxerr;
- case let n: int =>
- if (n != 0) {
- return par.line: syntaxerr;
- };
};
};
diff --git a/net/dns/decode.ha b/net/dns/decode.ha
@@ -109,15 +109,13 @@ fn decode_name(dec: *decoder) ([]str | format) = {
break;
};
- const name = dec.cur[..z];
+ const name = strings::fromutf8(dec.cur[..z]);
dec.cur = dec.cur[z..];
- for (let i = 0z; i < len(name); i += 1) {
- if (!ascii::valid(name[i]: u32: rune)) {
- return format;
- };
+ if (!ascii::validstr(name)) {
+ return format;
};
- append(names, strings::dup(strings::fromutf8(name)));
+ append(names, strings::dup(name));
};
return names;
};