mirror of
https://github.com/shivammathur/setup-php.git
synced 2026-05-15 01:50:57 +07:00
GHSA-pqwm-q9pv-ph8r - Fix CWE-78 [skip ci]
Co-Authored-By: maki <amarrec@quarkslab.com>
This commit is contained in:
@@ -13,4 +13,17 @@ describe('Config tests', () => {
|
||||
`('checking addINIValues on $os', async ({ini_values, os, output}) => {
|
||||
expect(await config.addINIValues(ini_values, os)).toContain(output);
|
||||
});
|
||||
|
||||
it.each`
|
||||
ini_values | os | output
|
||||
${'disable_functions="exec,system"'} | ${'linux'} | ${'echo "disable_functions=exec,system" | sudo tee -a "${pecl_file:-${ini_file[@]}}"'}
|
||||
${'disable_functions="exec,system"'} | ${'win32'} | ${'Add-Content "$php_dir\\php.ini" "disable_functions=exec,system"'}
|
||||
${'a=$(id)'} | ${'linux'} | ${'echo "a=\'\\$(id)\'"'}
|
||||
${'a=$(id)'} | ${'win32'} | ${'Add-Content "$php_dir\\php.ini" "a=\'`$(id)\'"'}
|
||||
`(
|
||||
'addINIValues survives quoted values and escapes shell metas: $ini_values, $os',
|
||||
async ({ini_values, os, output}) => {
|
||||
expect(await config.addINIValues(ini_values, os)).toContain(output);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -187,6 +187,7 @@ describe('Tools tests', () => {
|
||||
${'1.2.3-dev'} | ${'tool'} | ${'phar'} | ${'1.2.3-dev'}
|
||||
${'1.2.3-alpha1'} | ${'tool'} | ${'phar'} | ${'1.2.3-alpha1'}
|
||||
${'1.2.3-alpha.1'} | ${'tool'} | ${'phar'} | ${'1.2.3-alpha.1'}
|
||||
${'1.>=0'} | ${'tool'} | ${'phar'} | ${'1.0'}
|
||||
`(
|
||||
'checking getVersion: $version, $tool, $type',
|
||||
async ({version, tool, type, expected}) => {
|
||||
@@ -321,6 +322,28 @@ describe('Tools tests', () => {
|
||||
expect(await tools.addPackage(data)).toContain(script);
|
||||
});
|
||||
|
||||
it.each`
|
||||
release | os | expected
|
||||
${'tool:>=1.2'} | ${'linux'} | ${'add_composer_tool tool "tool:>=1.2" user/ global'}
|
||||
${'tool:1.*'} | ${'linux'} | ${'add_composer_tool tool "tool:1.*" user/ global'}
|
||||
${'tool:>=1.2'} | ${'win32'} | ${'Add-ComposerTool tool "tool:>=1.2" user/ global'}
|
||||
${'psalm:^5||^6'} | ${'linux'} | ${'add_composer_tool tool "psalm:^5||^6" user/ global'}
|
||||
${'psalm:>=5,<6'} | ${'linux'} | ${'add_composer_tool tool "psalm:>=5,<6" user/ global'}
|
||||
`(
|
||||
'addPackage quotes constraint operators: $release, $os',
|
||||
async ({release, os, expected}) => {
|
||||
const data = getData({
|
||||
tool: 'tool',
|
||||
version: '>=1.2',
|
||||
repository: 'user/tool',
|
||||
os: os,
|
||||
scope: 'global'
|
||||
});
|
||||
data['release'] = release;
|
||||
expect(await tools.addPackage(data)).toContain(expected);
|
||||
}
|
||||
);
|
||||
|
||||
it.each`
|
||||
version | php_version | os | script
|
||||
${'latest'} | ${'8.0'} | ${'linux'} | ${'add_tool https://github.com/phar-io/phive/releases/download/3.2.1/phive-3.2.1.phar phive'}
|
||||
@@ -651,7 +674,7 @@ describe('Tools tests', () => {
|
||||
'add_devtools phpize',
|
||||
'add_tool https://github.com/phpmd/phpmd/releases/latest/download/phpmd.phar phpmd "--version"',
|
||||
'add_tool https://github.com/phpspec/phpspec/releases/latest/download/phpspec.phar phpspec "-V"',
|
||||
'add_composer_tool phpunit-bridge phpunit-bridge:5.6.* symfony/ global',
|
||||
'add_composer_tool phpunit-bridge "phpunit-bridge:5.6.*" symfony/ global',
|
||||
'add_composer_tool phpunit-polyfills phpunit-polyfills:1.0.1 yoast/ global',
|
||||
'add_protoc 1.2.3',
|
||||
'add_tool https://github.com/vimeo/psalm/releases/latest/download/psalm.phar psalm "-v"',
|
||||
@@ -711,7 +734,7 @@ describe('Tools tests', () => {
|
||||
'Add-ComposerTool codeception codeception codeception/ global',
|
||||
'Add-ComposerTool prestissimo prestissimo hirak/ global',
|
||||
'Add-ComposerTool automatic-composer-prefetcher automatic-composer-prefetcher narrowspark/ global',
|
||||
'Add-ComposerTool phinx phinx:1.2.* robmorgan/ scoped',
|
||||
'Add-ComposerTool phinx "phinx:1.2.*" robmorgan/ scoped',
|
||||
'Add-ComposerTool phinx phinx:^1.2 robmorgan/ global',
|
||||
'Add-ComposerTool tool tool:1.2.3 user/ global',
|
||||
'Add-ComposerTool tool tool:~1.2 user/ global'
|
||||
|
||||
@@ -50,12 +50,37 @@ describe('Utils tests', () => {
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('parseVersion rejects unsupported inputs', async () => {
|
||||
await expect(utils.parseVersion('foo')).rejects.toThrow(
|
||||
'Invalid PHP version:'
|
||||
);
|
||||
await expect(utils.parseVersion('8.x.1')).rejects.toThrow(
|
||||
'Invalid PHP version:'
|
||||
);
|
||||
});
|
||||
|
||||
it('parseVersion rejects unexpected manifest values', async () => {
|
||||
const fetchSpy = jest
|
||||
.spyOn(fetchModule, 'fetch')
|
||||
.mockResolvedValue({data: '{ "latest": "8.1.0" }'});
|
||||
await expect(utils.parseVersion('latest')).rejects.toThrow(
|
||||
'Invalid PHP version in manifest:'
|
||||
);
|
||||
fetchSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('checking parseIniFile', async () => {
|
||||
expect(await utils.parseIniFile('production')).toBe('production');
|
||||
expect(await utils.parseIniFile('development')).toBe('development');
|
||||
expect(await utils.parseIniFile('none')).toBe('none');
|
||||
expect(await utils.parseIniFile('php.ini-production')).toBe('production');
|
||||
expect(await utils.parseIniFile('php.ini-development')).toBe('development');
|
||||
expect(await utils.parseIniFile('/etc/php.ini-production')).toBe(
|
||||
'production'
|
||||
);
|
||||
expect(await utils.parseIniFile('/a-b/php.ini-development')).toBe(
|
||||
'development'
|
||||
);
|
||||
expect(await utils.parseIniFile('invalid')).toBe('production');
|
||||
});
|
||||
|
||||
@@ -91,6 +116,40 @@ describe('Utils tests', () => {
|
||||
).toEqual(['apcu', 'mbstring', 'pdo_pgsql', 'posix', 'session']);
|
||||
});
|
||||
|
||||
it('checking escapeForShell', () => {
|
||||
expect(utils.escapeForShell('plain', 'linux')).toBe('plain');
|
||||
expect(utils.escapeForShell('a"b', 'linux')).toBe('a\\"b');
|
||||
expect(utils.escapeForShell('a$b`c\\d"e', 'linux')).toBe(
|
||||
'a\\$b\\`c\\\\d\\"e'
|
||||
);
|
||||
expect(utils.escapeForShell('a$b`c"d', 'win32')).toBe('a`$b``c`"d');
|
||||
});
|
||||
|
||||
it('checking safeArg', () => {
|
||||
expect(utils.safeArg('plain', 'linux')).toBe('plain');
|
||||
expect(utils.safeArg('vendor-pkg/repo@v1.0.0', 'linux')).toBe(
|
||||
'vendor-pkg/repo@v1.0.0'
|
||||
);
|
||||
expect(utils.safeArg('phpcs:>=3.0', 'linux')).toBe('"phpcs:>=3.0"');
|
||||
expect(utils.safeArg('vendor/foo:1.*', 'linux')).toBe('"vendor/foo:1.*"');
|
||||
expect(utils.safeArg('foo$bar', 'linux')).toBe('"foo\\$bar"');
|
||||
expect(utils.safeArg('foo$bar', 'win32')).toBe('"foo`$bar"');
|
||||
expect(utils.safeArg('', 'linux')).toBe('');
|
||||
});
|
||||
|
||||
it('checking sanitizeShellInput', () => {
|
||||
expect(utils.sanitizeShellInput('mbstring, intl')).toBe('mbstring, intl');
|
||||
expect(utils.sanitizeShellInput('foo;ls;bar')).toBe('foolsbar');
|
||||
expect(utils.sanitizeShellInput('foo$(id)bar')).toBe('fooidbar');
|
||||
expect(utils.sanitizeShellInput('a`b`c\\d"e\'f')).toBe('abcdef');
|
||||
expect(utils.sanitizeShellInput('vendor/foo:1.*', true)).toBe(
|
||||
'vendor/foo:1.'
|
||||
);
|
||||
expect(utils.sanitizeShellInput('vendor/foo@feat?ure', true)).toBe(
|
||||
'vendor/foo@feature'
|
||||
);
|
||||
});
|
||||
|
||||
it('checking INIArray', async () => {
|
||||
expect(await utils.CSVArray('a=1, b=2, c=3')).toEqual([
|
||||
'a=1',
|
||||
@@ -291,7 +350,7 @@ describe('Utils tests', () => {
|
||||
|
||||
existsSync.mockReturnValue(true);
|
||||
readFileSync.mockReturnValue('setup-php');
|
||||
expect(await utils.readPHPVersion()).toBe('setup-php');
|
||||
await expect(utils.readPHPVersion()).rejects.toThrow('Invalid PHP version');
|
||||
|
||||
existsSync.mockReturnValueOnce(false).mockReturnValueOnce(true);
|
||||
readFileSync.mockReturnValue(
|
||||
@@ -312,6 +371,45 @@ describe('Utils tests', () => {
|
||||
readFileSync.mockClear();
|
||||
});
|
||||
|
||||
it('readPHPVersion rejects unsupported values from each source', async () => {
|
||||
const existsSync = jest.spyOn(fs, 'existsSync').mockImplementation();
|
||||
const readFileSync = jest.spyOn(fs, 'readFileSync').mockImplementation();
|
||||
|
||||
process.env['php-version'] = 'bogus';
|
||||
await expect(utils.readPHPVersion()).rejects.toThrow(
|
||||
'Invalid PHP version in php-version input'
|
||||
);
|
||||
delete process.env['php-version'];
|
||||
|
||||
existsSync.mockReturnValue(true);
|
||||
readFileSync.mockReturnValue('bogus');
|
||||
await expect(utils.readPHPVersion()).rejects.toThrow(
|
||||
'Invalid PHP version in .php-version'
|
||||
);
|
||||
|
||||
existsSync.mockReturnValueOnce(false).mockReturnValueOnce(true);
|
||||
readFileSync.mockReturnValue(
|
||||
JSON.stringify({'platform-overrides': {php: 'bogus'}})
|
||||
);
|
||||
await expect(utils.readPHPVersion()).rejects.toThrow(
|
||||
'Invalid PHP version in composer.lock platform-overrides.php'
|
||||
);
|
||||
|
||||
existsSync
|
||||
.mockReturnValueOnce(false)
|
||||
.mockReturnValueOnce(false)
|
||||
.mockReturnValueOnce(true);
|
||||
readFileSync.mockReturnValue(
|
||||
JSON.stringify({config: {platform: {php: 'bogus'}}})
|
||||
);
|
||||
await expect(utils.readPHPVersion()).rejects.toThrow(
|
||||
'Invalid PHP version in composer.json config.platform.php'
|
||||
);
|
||||
|
||||
existsSync.mockClear();
|
||||
readFileSync.mockClear();
|
||||
});
|
||||
|
||||
it('checking setVariable', async () => {
|
||||
let script: string = await utils.setVariable('var', 'command', 'linux');
|
||||
expect(script).toEqual('\nvar="$(command)"\n');
|
||||
|
||||
Reference in New Issue
Block a user