encoding/utf8: enforce scalar and buffer bounds
This commit is contained in:
@@ -300,11 +300,13 @@ export fn runesz(r: rune) i32 = {
|
||||
// codepoint that starts with `c`, or `invalid` if `c` cannot start
|
||||
// a legal UTF-8 sequence. Constants written in decimal because ww
|
||||
// doesn't accept Hare's `0b1000_0000` binary syntax: 0x80=128,
|
||||
// 0xC2=194, 0xE0=224, 0xF0=240, 0xF8=248.
|
||||
// 0xC2=194, 0xE0=224, 0xF0=240, 0xF5=245.
|
||||
export fn utf8sz(c: u8) (i32 | invalid) = {
|
||||
if (c < 128u8) { return 1; };
|
||||
if (c < 194u8) { let e: invalid; return e; };
|
||||
if (c >= 248u8) { let e: invalid; return e; };
|
||||
// F4 is the last legal four-byte lead: F4 8F BF BF encodes
|
||||
// U+10FFFF. F5 and above cannot begin a Unicode scalar value.
|
||||
if (c >= 245u8) { let e: invalid; return e; };
|
||||
if (c < 224u8) { return 2; };
|
||||
if (c < 240u8) { return 3; };
|
||||
return 4;
|
||||
@@ -340,6 +342,7 @@ export fn encoderune(out: []u8, r: rune) i32 = {
|
||||
} else {
|
||||
first = 0xF0u8; n = 4;
|
||||
};
|
||||
assert(out.len >= n, "utf8.encoderune: output buffer is too small");
|
||||
|
||||
let v: u32 = ch;
|
||||
let i: i32 = n - 1;
|
||||
@@ -431,12 +434,16 @@ export fn remaining(d: *decoder) []u8 = {
|
||||
};
|
||||
|
||||
// ref/hare/encoding/utf8/decode.ha:80. Borrowed view of the bytes
|
||||
// between two decoders' positions. Precondition (Hare asserts both):
|
||||
// the decoders share the same source, and `begin.offs <= end.offs`.
|
||||
// between two decoders' positions. The decoders must share one complete
|
||||
// source view, both offsets must remain in that view, and begin must not
|
||||
// follow end.
|
||||
export fn slice(begin: *decoder, end: *decoder) []u8 = {
|
||||
if (begin.src.ptr != end.src.ptr) {
|
||||
if (begin.src.ptr != end.src.ptr || begin.src.len != end.src.len) {
|
||||
abort("utf8.slice: decoders from different sources");
|
||||
};
|
||||
if (begin.offs > begin.src.len: size || end.offs > end.src.len: size) {
|
||||
abort("utf8.slice: decoder offset past end of source");
|
||||
};
|
||||
if (begin.offs > end.offs) {
|
||||
abort("utf8.slice: begin past end");
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user