diff --git a/test/parallel/test-buffer-alloc.js b/test/parallel/test-buffer-alloc.js index 597b925be20f43..1368136abe8f22 100644 --- a/test/parallel/test-buffer-alloc.js +++ b/test/parallel/test-buffer-alloc.js @@ -314,6 +314,8 @@ assert.strictEqual((Buffer.from('Woman')).toString('base64url'), 'V29tYW4'); Buffer.from(expected)); } +const base64flavors = ['base64', 'base64url']; + { // Test that regular and URL-safe base64 both work both ways with padding const expected = [0xff, 0xff, 0xbe, 0xff, 0xef, 0xbf, 0xfb, 0xef, 0xff, 0xfb]; @@ -341,137 +343,182 @@ assert.strictEqual((Buffer.from('Woman')).toString('base64url'), 'V29tYW4'); 'dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZ' + 'GdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm' + '5hbCBwbGVhc3VyZS4='; - assert.strictEqual((Buffer.from(quote)).toString('base64'), expected); - - let b = Buffer.allocUnsafe(1024); - let bytesWritten = b.write(expected, 0, 'base64'); - assert.strictEqual(quote.length, bytesWritten); - assert.strictEqual(quote, b.toString('ascii', 0, quote.length)); - - // Check that the base64 decoder ignores whitespace - const expectedWhite = `${expected.slice(0, 60)} \n` + - `${expected.slice(60, 120)} \n` + - `${expected.slice(120, 180)} \n` + - `${expected.slice(180, 240)} \n` + - `${expected.slice(240, 300)}\n` + - `${expected.slice(300, 360)}\n`; - b = Buffer.allocUnsafe(1024); - bytesWritten = b.write(expectedWhite, 0, 'base64'); - assert.strictEqual(quote.length, bytesWritten); - assert.strictEqual(quote, b.toString('ascii', 0, quote.length)); - - // Check that the base64 decoder on the constructor works - // even in the presence of whitespace. - b = Buffer.from(expectedWhite, 'base64'); - assert.strictEqual(quote.length, b.length); - assert.strictEqual(quote, b.toString('ascii', 0, quote.length)); - - // Check that the base64 decoder ignores illegal chars - const expectedIllegal = expected.slice(0, 60) + ' \x80' + - expected.slice(60, 120) + ' \xff' + - expected.slice(120, 180) + ' \x00' + - expected.slice(180, 240) + ' \x98' + - expected.slice(240, 300) + '\x03' + - expected.slice(300, 360); - b = Buffer.from(expectedIllegal, 'base64'); - assert.strictEqual(quote.length, b.length); - assert.strictEqual(quote, b.toString('ascii', 0, quote.length)); + assert.strictEqual(Buffer.from(quote).toString('base64'), expected); + assert.strictEqual( + Buffer.from(quote).toString('base64url'), + expected.replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '') + ); + + base64flavors.forEach((encoding) => { + let b = Buffer.allocUnsafe(1024); + let bytesWritten = b.write(expected, 0, encoding); + assert.strictEqual(quote.length, bytesWritten); + assert.strictEqual(quote, b.toString('ascii', 0, quote.length)); + + // Check that the base64 decoder ignores whitespace + const expectedWhite = `${expected.slice(0, 60)} \n` + + `${expected.slice(60, 120)} \n` + + `${expected.slice(120, 180)} \n` + + `${expected.slice(180, 240)} \n` + + `${expected.slice(240, 300)}\n` + + `${expected.slice(300, 360)}\n`; + b = Buffer.allocUnsafe(1024); + bytesWritten = b.write(expectedWhite, 0, encoding); + assert.strictEqual(quote.length, bytesWritten); + assert.strictEqual(quote, b.toString('ascii', 0, quote.length)); + + // Check that the base64 decoder on the constructor works + // even in the presence of whitespace. + b = Buffer.from(expectedWhite, encoding); + assert.strictEqual(quote.length, b.length); + assert.strictEqual(quote, b.toString('ascii', 0, quote.length)); + + // Check that the base64 decoder ignores illegal chars + const expectedIllegal = expected.slice(0, 60) + ' \x80' + + expected.slice(60, 120) + ' \xff' + + expected.slice(120, 180) + ' \x00' + + expected.slice(180, 240) + ' \x98' + + expected.slice(240, 300) + '\x03' + + expected.slice(300, 360); + b = Buffer.from(expectedIllegal, encoding); + assert.strictEqual(quote.length, b.length); + assert.strictEqual(quote, b.toString('ascii', 0, quote.length)); + }); } -assert.strictEqual(Buffer.from('', 'base64').toString(), ''); -assert.strictEqual(Buffer.from('K', 'base64').toString(), ''); - -// multiple-of-4 with padding -assert.strictEqual(Buffer.from('Kg==', 'base64').toString(), '*'); -assert.strictEqual(Buffer.from('Kio=', 'base64').toString(), '*'.repeat(2)); -assert.strictEqual(Buffer.from('Kioq', 'base64').toString(), '*'.repeat(3)); -assert.strictEqual(Buffer.from('KioqKg==', 'base64').toString(), '*'.repeat(4)); -assert.strictEqual(Buffer.from('KioqKio=', 'base64').toString(), '*'.repeat(5)); -assert.strictEqual(Buffer.from('KioqKioq', 'base64').toString(), '*'.repeat(6)); -assert.strictEqual(Buffer.from('KioqKioqKg==', 'base64').toString(), - '*'.repeat(7)); -assert.strictEqual(Buffer.from('KioqKioqKio=', 'base64').toString(), - '*'.repeat(8)); -assert.strictEqual(Buffer.from('KioqKioqKioq', 'base64').toString(), - '*'.repeat(9)); -assert.strictEqual(Buffer.from('KioqKioqKioqKg==', 'base64').toString(), - '*'.repeat(10)); -assert.strictEqual(Buffer.from('KioqKioqKioqKio=', 'base64').toString(), - '*'.repeat(11)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioq', 'base64').toString(), - '*'.repeat(12)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKg==', 'base64').toString(), - '*'.repeat(13)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKio=', 'base64').toString(), - '*'.repeat(14)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioq', 'base64').toString(), - '*'.repeat(15)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKg==', 'base64').toString(), - '*'.repeat(16)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKio=', 'base64').toString(), - '*'.repeat(17)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKioq', 'base64').toString(), - '*'.repeat(18)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKioqKg==', - 'base64').toString(), - '*'.repeat(19)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKioqKio=', - 'base64').toString(), - '*'.repeat(20)); - -// No padding, not a multiple of 4 -assert.strictEqual(Buffer.from('Kg', 'base64').toString(), '*'); -assert.strictEqual(Buffer.from('Kio', 'base64').toString(), '*'.repeat(2)); -assert.strictEqual(Buffer.from('KioqKg', 'base64').toString(), '*'.repeat(4)); -assert.strictEqual(Buffer.from('KioqKio', 'base64').toString(), '*'.repeat(5)); -assert.strictEqual(Buffer.from('KioqKioqKg', 'base64').toString(), - '*'.repeat(7)); -assert.strictEqual(Buffer.from('KioqKioqKio', 'base64').toString(), - '*'.repeat(8)); -assert.strictEqual(Buffer.from('KioqKioqKioqKg', 'base64').toString(), - '*'.repeat(10)); -assert.strictEqual(Buffer.from('KioqKioqKioqKio', 'base64').toString(), - '*'.repeat(11)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKg', 'base64').toString(), - '*'.repeat(13)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKio', 'base64').toString(), - '*'.repeat(14)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKg', 'base64').toString(), - '*'.repeat(16)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKio', 'base64').toString(), - '*'.repeat(17)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKioqKg', - 'base64').toString(), - '*'.repeat(19)); -assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKioqKio', - 'base64').toString(), - '*'.repeat(20)); +base64flavors.forEach((encoding) => { + assert.strictEqual(Buffer.from('', encoding).toString(), ''); + assert.strictEqual(Buffer.from('K', encoding).toString(), ''); + + // multiple-of-4 with padding + assert.strictEqual(Buffer.from('Kg==', encoding).toString(), '*'); + assert.strictEqual(Buffer.from('Kio=', encoding).toString(), '*'.repeat(2)); + assert.strictEqual(Buffer.from('Kioq', encoding).toString(), '*'.repeat(3)); + assert.strictEqual( + Buffer.from('KioqKg==', encoding).toString(), '*'.repeat(4)); + assert.strictEqual( + Buffer.from('KioqKio=', encoding).toString(), '*'.repeat(5)); + assert.strictEqual( + Buffer.from('KioqKioq', encoding).toString(), '*'.repeat(6)); + assert.strictEqual(Buffer.from('KioqKioqKg==', encoding).toString(), + '*'.repeat(7)); + assert.strictEqual(Buffer.from('KioqKioqKio=', encoding).toString(), + '*'.repeat(8)); + assert.strictEqual(Buffer.from('KioqKioqKioq', encoding).toString(), + '*'.repeat(9)); + assert.strictEqual(Buffer.from('KioqKioqKioqKg==', encoding).toString(), + '*'.repeat(10)); + assert.strictEqual(Buffer.from('KioqKioqKioqKio=', encoding).toString(), + '*'.repeat(11)); + assert.strictEqual(Buffer.from('KioqKioqKioqKioq', encoding).toString(), + '*'.repeat(12)); + assert.strictEqual(Buffer.from('KioqKioqKioqKioqKg==', encoding).toString(), + '*'.repeat(13)); + assert.strictEqual(Buffer.from('KioqKioqKioqKioqKio=', encoding).toString(), + '*'.repeat(14)); + assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioq', encoding).toString(), + '*'.repeat(15)); + assert.strictEqual( + Buffer.from('KioqKioqKioqKioqKioqKg==', encoding).toString(), + '*'.repeat(16)); + assert.strictEqual( + Buffer.from('KioqKioqKioqKioqKioqKio=', encoding).toString(), + '*'.repeat(17)); + assert.strictEqual( + Buffer.from('KioqKioqKioqKioqKioqKioq', encoding).toString(), + '*'.repeat(18)); + assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKioqKg==', + encoding).toString(), + '*'.repeat(19)); + assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKioqKio=', + encoding).toString(), + '*'.repeat(20)); + + // No padding, not a multiple of 4 + assert.strictEqual(Buffer.from('Kg', encoding).toString(), '*'); + assert.strictEqual(Buffer.from('Kio', encoding).toString(), '*'.repeat(2)); + assert.strictEqual(Buffer.from('KioqKg', encoding).toString(), '*'.repeat(4)); + assert.strictEqual( + Buffer.from('KioqKio', encoding).toString(), '*'.repeat(5)); + assert.strictEqual(Buffer.from('KioqKioqKg', encoding).toString(), + '*'.repeat(7)); + assert.strictEqual(Buffer.from('KioqKioqKio', encoding).toString(), + '*'.repeat(8)); + assert.strictEqual(Buffer.from('KioqKioqKioqKg', encoding).toString(), + '*'.repeat(10)); + assert.strictEqual(Buffer.from('KioqKioqKioqKio', encoding).toString(), + '*'.repeat(11)); + assert.strictEqual(Buffer.from('KioqKioqKioqKioqKg', encoding).toString(), + '*'.repeat(13)); + assert.strictEqual(Buffer.from('KioqKioqKioqKioqKio', encoding).toString(), + '*'.repeat(14)); + assert.strictEqual(Buffer.from('KioqKioqKioqKioqKioqKg', encoding).toString(), + '*'.repeat(16)); + assert.strictEqual( + Buffer.from('KioqKioqKioqKioqKioqKio', encoding).toString(), + '*'.repeat(17)); + assert.strictEqual( + Buffer.from('KioqKioqKioqKioqKioqKioqKg', encoding).toString(), + '*'.repeat(19)); + assert.strictEqual( + Buffer.from('KioqKioqKioqKioqKioqKioqKio', encoding).toString(), + '*'.repeat(20)); +}); // Handle padding graciously, multiple-of-4 or not assert.strictEqual( Buffer.from('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw==', 'base64').length, 32 ); +assert.strictEqual( + Buffer.from('72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw==', 'base64url') + .length, + 32 +); assert.strictEqual( Buffer.from('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw=', 'base64').length, 32 ); +assert.strictEqual( + Buffer.from('72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw=', 'base64url') + .length, + 32 +); assert.strictEqual( Buffer.from('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw', 'base64').length, 32 ); +assert.strictEqual( + Buffer.from('72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw', 'base64url') + .length, + 32 +); assert.strictEqual( Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==', 'base64').length, 31 ); +assert.strictEqual( + Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==', 'base64url') + .length, + 31 +); assert.strictEqual( Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=', 'base64').length, 31 ); +assert.strictEqual( + Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=', 'base64url') + .length, + 31 +); assert.strictEqual( Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg', 'base64').length, 31 ); +assert.strictEqual( + Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg', 'base64url').length, + 31 +); { // This string encodes single '.' character in UTF-16 @@ -483,6 +530,16 @@ assert.strictEqual( assert.strictEqual(dot.toString('base64'), '//4uAA=='); } +{ +// This string encodes single '.' character in UTF-16 + const dot = Buffer.from('//4uAA', 'base64url'); + assert.strictEqual(dot[0], 0xff); + assert.strictEqual(dot[1], 0xfe); + assert.strictEqual(dot[2], 0x2e); + assert.strictEqual(dot[3], 0x00); + assert.strictEqual(dot.toString('base64url'), '__4uAA'); +} + { // Writing base64 at a position > 0 should not mangle the result. // @@ -498,6 +555,21 @@ assert.strictEqual( 'Madness?! This is node.js!'); } +{ + // Writing base64url at a position > 0 should not mangle the result. + // + // https://github.com/joyent/node/issues/402 + const segments = ['TWFkbmVzcz8h', 'IFRoaXM', 'IGlz', 'IG5vZGUuanMh']; + const b = Buffer.allocUnsafe(64); + let pos = 0; + + for (let i = 0; i < segments.length; ++i) { + pos += b.write(segments[i], pos, 'base64url'); + } + assert.strictEqual(b.toString('latin1', 0, pos), + 'Madness?! This is node.js!'); +} + // Regression test for https://github.com/nodejs/node/issues/3496. assert.strictEqual(Buffer.from('=bad'.repeat(1e4), 'base64').length, 0);