Skip to content

Commit

Permalink
[Fix] write until an error
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Jul 8, 2024
1 parent 7810f65 commit eb8d6c4
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 28 deletions.
16 changes: 8 additions & 8 deletions Uint8Array.prototype.setFromBase64/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,21 @@ module.exports = function setFromBase64(string) {

var result = FromBase64(string, alphabet, lastChunkHandling, byteLength); // step 14

if (result['[[Error]]']) { // step 15
throw result['[[Error]]']; // step 15.a
}

var bytes = result['[[Bytes]]']; // step 16
var bytes = result['[[Bytes]]']; // step 15

var written = bytes.length; // step 17
var written = bytes.length; // step 16

// 18. NOTE: FromBase64 does not invoke any user code, so the ArrayBuffer backing into cannot have been detached or shrunk.
// 17. NOTE: FromBase64 does not invoke any user code, so the ArrayBuffer backing into cannot have been detached or shrunk.

if (written > byteLength) {
throw new $TypeError('Assertion failed: written is not <= byteLength'); // step 19
}

SetUint8ArrayBytes(into, bytes); // step 20
SetUint8ArrayBytes(into, bytes); // step 19

if (result['[[Error]]']) { // step 20
throw result['[[Error]]']; // step 20.a
}

var offset = typedArrayByteOffset(into); // step 21

Expand Down
18 changes: 9 additions & 9 deletions Uint8Array.prototype.setFromHex/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,21 @@ module.exports = function setFromHex(string) {

var result = FromHex(string, byteLength); // step 7

if (result['[[Error]]']) { // step 8
throw result['[[Error]]']; // step 8.a
}

var bytes = result['[[Bytes]]']; // step 9
var bytes = result['[[Bytes]]']; // step 8

var written = bytes.length; // step 10
var written = bytes.length; // step 9

// 11. NOTE: FromHex does not invoke any user code, so the ArrayBuffer backing into cannot have been detached or shrunk.
// 10. NOTE: FromHex does not invoke any user code, so the ArrayBuffer backing into cannot have been detached or shrunk.

if (written > byteLength) {
throw new $TypeError('Assertion failed: written is not <= byteLength'); // step 12
throw new $TypeError('Assertion failed: written is not <= byteLength'); // step 11
}

SetUint8ArrayBytes(into, bytes); // step 13
SetUint8ArrayBytes(into, bytes); // step 12

if (result['[[Error]]']) { // step 13
throw result['[[Error]]']; // step 13.a
}

// var resultObject = {}; // step 14 // OrdinaryObjectCreate(%Object.prototype%)
// CreateDataPropertyOrThrow(resultObject, 'read', result['[[Read]]']); // step 15
Expand Down
34 changes: 23 additions & 11 deletions aos/FromHex.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,38 @@ module.exports = function FromHex(string) {

var length = string.length; // step 2

if (modulo(length, 2) !== 0) {
throw new $SyntaxError('string should be an even number of characters'); // step 3
}
var bytes = []; // step 3

var bytes = []; // step 4
var read = 0; // step 4

var index = 0; // step 5
if (modulo(length, 2) !== 0) { // step 5
return {
'[[Read]]': read,
'[[Bytes]]': bytes,
'[[Error]]': new $SyntaxError('string should be an even number of characters')
};
}

while (index < length && bytes.length < maxLength) { // step 6
var hexits = substring(string, index, index + 2); // step 6.a
while (read < length && bytes.length < maxLength) { // step 6
var hexits = substring(string, read, read + 2); // step 6.a

if (!isHexDigit(hexits)) {
throw new $SyntaxError('string should only contain hex characters'); // step 6.b
if (!isHexDigit(hexits)) { // step 6.b
return {
'[[Read]]': read,
'[[Bytes]]': bytes,
'[[Error]]': new $SyntaxError('string should only contain hex characters')
};
}

index += 2; // step 6.c
read += 2; // step 6.c

var byte = $parseInt(hexits, 16); // step 6.d

$push(bytes, byte); // step 6.e
}
return { '[[Read]]': index, '[[Bytes]]': bytes }; // step 7
return {
'[[Read]]': read,
'[[Bytes]]': bytes,
'[[Error]]': null
}; // step 7
};
40 changes: 40 additions & 0 deletions test/Uint8Array.prototype.setFromBase64.js
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,46 @@ module.exports = {
s2t.end();
});

st.test('test262: test/built-ins/Uint8Array/prototype/setFromBase64/writes-up-to-error', function (s2t) {
var target = new Uint8Array([255, 255, 255, 255, 255]);
s2t['throws'](
function () { method(target, 'MjYyZm.9v'); },
SyntaxError,
'illegal character in second chunk'
);
s2t.deepEqual(
target,
new Uint8Array([50, 54, 50, 255, 255]),
'decoding from MjYyZm.9v should only write the valid chunks'
);

var target2 = new Uint8Array([255, 255, 255, 255, 255]);
s2t['throws'](
function () { method(target2, 'MjYyZg', { lastChunkHandling: 'strict' }); },
SyntaxError,
'padding omitted with lastChunkHandling: strict'
);
s2t.deepEqual(
target2,
new Uint8Array([50, 54, 50, 255, 255]),
'decoding from MjYyZg should only write the valid chunks'
);

var target3 = new Uint8Array([255, 255, 255, 255, 255]);
s2t['throws'](
function () { method(target3, 'MjYyZg==='); },
SyntaxError,
'extra characters after padding'
);
s2t.deepEqual(
target3,
new Uint8Array([50, 54, 50, 255, 255]),
'decoding from MjYyZg=== should not write the last chunk because it has extra padding'
);

s2t.end();
});

var illegal = [
'Zm.9v',
'Zm9v^',
Expand Down
20 changes: 20 additions & 0 deletions test/Uint8Array.prototype.setFromHex.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,26 @@ module.exports = {
s2t.end();
});

st.test('test262: test/built-ins/Uint8Array/prototype/setFromHex/writes-up-to-error', function (s2t) {
['aaa ', 'aaag'].forEach(function (value) {
var target = new Uint8Array([255, 255, 255, 255, 255]);
s2t['throws'](
function () { method(target, value); },
SyntaxError
);
s2t.deepEqual(target, new Uint8Array([170, 255, 255, 255, 255]), 'decoding from ' + value);
});

var target = new Uint8Array([255, 255, 255, 255, 255]);
s2t['throws'](
function () { method(target, 'aaa'); },
SyntaxError
);
s2t.deepEqual(target, new Uint8Array([255, 255, 255, 255, 255]), 'when length is odd no data is written');

s2t.end();
});

st.end();
});
},
Expand Down
19 changes: 19 additions & 0 deletions test/Uint8Array.prototype.toBase64.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,25 @@ module.exports = {
s2t.end();
});

st.test('test262: test/built-ins/Uint8Array/prototype/toBase64/omit-padding', function (s2t) {
s2t.equal(method(new Uint8Array([199, 239])), 'x+8=');
s2t.equal(method(new Uint8Array([199, 239]), { omitPadding: false }), 'x+8=');
s2t.equal(method(new Uint8Array([199, 239]), { omitPadding: true }), 'x+8');
s2t.equal(method(new Uint8Array([255]), { omitPadding: true }), '/w');

// works with base64url alphabet
s2t.equal(method(new Uint8Array([199, 239]), { alphabet: 'base64url' }), 'x-8=');
s2t.equal(method(new Uint8Array([199, 239]), { alphabet: 'base64url', omitPadding: false }), 'x-8=');
s2t.equal(method(new Uint8Array([199, 239]), { alphabet: 'base64url', omitPadding: true }), 'x-8');
s2t.equal(method(new Uint8Array([255]), { alphabet: 'base64url', omitPadding: true }), '_w');

// performs ToBoolean on the argument
s2t.equal(method(new Uint8Array([255]), { omitPadding: 0 }), '/w==');
s2t.equal(method(new Uint8Array([255]), { omitPadding: 1 }), '/w');

s2t.end();
});

// standard test vectors from https://datatracker.ietf.org/doc/html/rfc4648#section-10
st.equal(method(new Uint8Array([])), '');
st.equal(method(new Uint8Array([102])), 'Zg==');
Expand Down

0 comments on commit eb8d6c4

Please sign in to comment.