hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mascii/strcmp.ha | 28+++++++---------------------
Mformat/xml/parser.ha | 20++++++++------------
Mnet/dns/decode.ha | 10++++------
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; };