From 6b285a89796cb12f9db655d2ce894f9c8924b999 Mon Sep 17 00:00:00 2001 From: MarkXian Date: Sat, 1 Aug 2026 16:44:20 +0800 Subject: [PATCH] fix(rgb): reject non-numeric channels --- src/io/rgb/index.js | 10 ++++++++++ test/autodetect.test.js | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/io/rgb/index.js b/src/io/rgb/index.js index c903dc96..0b606b6e 100644 --- a/src/io/rgb/index.js +++ b/src/io/rgb/index.js @@ -18,8 +18,17 @@ Color.prototype.rgba = function (rnd = true) { const rgb = (...args) => new Color(...args, 'rgb'); Object.assign(chroma, { rgb }); +const isValidChannel = (value) => + type(value) === 'number' && !Number.isNaN(value); + input.format.rgb = (...args) => { const rgba = unpack(args, 'rgba'); + if (!rgba.slice(0, 3).every(isValidChannel)) { + throw new Error('invalid rgb color'); + } + if (rgba[3] !== undefined && !isValidChannel(rgba[3])) { + throw new Error('invalid rgb color'); + } if (rgba[3] === undefined) rgba[3] = 1; return rgba; }; @@ -30,6 +39,7 @@ input.autodetect.push({ args = unpack(args, 'rgba'); if ( type(args) === 'array' && + args.slice(0, 3).every(isValidChannel) && (args.length === 3 || (args.length === 4 && type(args[3]) == 'number' && diff --git a/test/autodetect.test.js b/test/autodetect.test.js index 258c6851..44d5afdb 100644 --- a/test/autodetect.test.js +++ b/test/autodetect.test.js @@ -35,6 +35,16 @@ describe('autodetect color', () => { expect(result.hex()).toBe('#0000ff'); }); + it('rejects non-numeric RGB channels', () => { + expect(() => chroma('nonsense', 0, 255, 'rgb')).toThrow('invalid rgb color'); + expect(() => chroma(null, 0, 255, 'rgb')).toThrow('invalid rgb color'); + }); + + it('still clips out-of-range numeric RGB channels', () => { + expect(chroma(-1000, 0, 255, 'rgb').hex()).toBe('#0000ff'); + expect(chroma(1000, 0, 255, 'rgb').hex()).toBe('#ff00ff'); + }); + it('autodetect rgba color', () => { const result = chroma(255, 0, 0, 0.5); expect(result.css()).toBe('rgb(255 0 0 / 0.5)');