From cf18d58447aba4359acf3072907fb39745846d59 Mon Sep 17 00:00:00 2001 From: Paul Bouchon Date: Sat, 11 Jul 2026 22:20:01 -0400 Subject: [PATCH] fix: handle double quotes inside single-quoted GYP strings parseConfigGypi() converted single quotes to double quotes with a bare `config.replace(/'/g, '"')`, which produced invalid JSON when a single-quoted string contained double-quote characters, such as the GYP condition strings used by native addons (e.g. `'OS=="win"'`). Convert each single-quoted string individually and escape the double quotes inside it instead. Fixes: https://github.com/nodejs/node-gyp/issues/3333 Signed-off-by: Paul Bouchon --- lib/create-config-gypi.js | 9 +++++++-- test/test-create-config-gypi.js | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/create-config-gypi.js b/lib/create-config-gypi.js index d471da5169..5bf6ca945e 100644 --- a/lib/create-config-gypi.js +++ b/lib/create-config-gypi.js @@ -10,8 +10,13 @@ function parseConfigGypi (config) { config = config.replace(/#.*/g, '') // 2. join multiline strings config = config.replace(/'$\s+'/mg, '') - // 3. normalize string literals from ' into " - config = config.replace(/'/g, '"') + // 3. normalize string literals from ' into ", escaping any double-quote + // characters that appear inside a single-quoted string (e.g. GYP condition + // strings such as 'OS=="win"') so the result is still valid JSON + config = config.replace(/'(?:[^'\\]|\\.)*'/g, (str) => { + const inner = str.slice(1, -1).replace(/\\'/g, "'").replace(/"/g, '\\"') + return `"${inner}"` + }) return JSON.parse(config) } diff --git a/test/test-create-config-gypi.js b/test/test-create-config-gypi.js index 602fd3d678..30cd291b67 100644 --- a/test/test-create-config-gypi.js +++ b/test/test-create-config-gypi.js @@ -76,4 +76,10 @@ describe('create-config-gypi', function () { const config = parseConfigGypi(str) assert.deepStrictEqual(config, { variables: { multiline: 'AB' } }) }) + + it('config.gypi parsing with double quotes inside single-quoted strings', function () { + const str = '{\'variables\': {\'cond\': \'OS=="win"\', \'flags\': \'-DFOO="x"\'}}' + const config = parseConfigGypi(str) + assert.deepStrictEqual(config, { variables: { cond: 'OS=="win"', flags: '-DFOO="x"' } }) + }) })