From d2046bc1ec7a1d3ae53dfc88f7b5522944dbd68d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sat, 22 Jul 2023 11:38:06 +0200 Subject: [PATCH 1/2] Add tests to Search input validation methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Krög --- js/src/table/change.js | 46 ++++++++++---- test/javascript/change.test.js | 107 +++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 13 deletions(-) create mode 100644 test/javascript/change.test.js diff --git a/js/src/table/change.js b/js/src/table/change.js index 903fe539502c..abca8735690d 100644 --- a/js/src/table/change.js +++ b/js/src/table/change.js @@ -150,6 +150,31 @@ function checkForCheckbox (multiEdit) { return true; } +/** + * @test-module Change + */ +var Change = {}; + +/** + * Validator method for IN(...), NOT IN(...) + * BETWEEN and NOT BETWEEN + * @param {string} value + * @return {boolean} + */ +Change.validationFunctionForMultipleInt = function (value) { + return value.match(/^(((0x[0-9a-f]+)|([+-]?([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)(e[+-]?[0-9]+)?))(,|$))+$/i) !== null; +}; + +/** + * Validator method for INTs + * See all possible syntaxes in tests of https://regexr.com/7h1ci + * @param {string} value + * @return {boolean} + */ +Change.validationFunctionForInt = function (value) { + return value.match(/^(0x[0-9a-f]+$)|([+-]?([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)(e[+-]?[0-9]+)?)$/i) !== null; +}; + // used in Search page mostly for INT fields // eslint-disable-next-line no-unused-vars function verifyAfterSearchFieldChange (index, searchFormId) { @@ -174,22 +199,17 @@ function verifyAfterSearchFieldChange (index, searchFormId) { $(element).valid(); } }); - // validator method for IN(...), NOT IN(...) - // BETWEEN and NOT BETWEEN - // See all possible syntaxes in tests of https://regexr.com/7h1eq - jQuery.validator.addMethod('validationFunctionForMultipleInt', function (value) { - return value.match(/^(((0x[0-9a-f]+)|([+-]?([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)(e[+-]?[0-9]+)?))(,|$))+$/i) !== null; - }, - Messages.strEnterValidNumber + jQuery.validator.addMethod( + 'validationFunctionForMultipleInt', + Change.validationFunctionForMultipleInt, + Messages.strEnterValidNumber ); validateMultipleIntField($thisInput, true); } else { - // validator method for INTs - // See all possible syntaxes in tests of https://regexr.com/7h1ci - jQuery.validator.addMethod('validationFunctionForInt', function (value) { - return value.match(/^(0x[0-9a-f]+$)|([+-]?([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)(e[+-]?[0-9]+)?)$/i) !== null; - }, - Messages.strEnterValidNumber + jQuery.validator.addMethod( + 'validationFunctionForInt', + Change.validationFunctionForInt, + Messages.strEnterValidNumber ); $(searchFormId).validate({ // update errors as we write diff --git a/test/javascript/change.test.js b/test/javascript/change.test.js new file mode 100644 index 000000000000..a82705b77b83 --- /dev/null +++ b/test/javascript/change.test.js @@ -0,0 +1,107 @@ +/* eslint-env node, jest */ + +const Change = require('phpmyadmin/table/change'); + +describe('change', () => { + function testSingle (fn) { + test('empty string', function () { + expect(fn('')).toBe(false); + }); + test('whitespace string', function () { + expect(fn(' ')).toBe(false); + }); + test('space around', function () { + expect(fn(' 2 ')).toBe(true); + }); + test('exponential', function () { + expect(fn('102823466E+38')).toBe(true); + }); + test('negative decimal', function () { + expect(fn('-3.402823466')).toBe(true); + }); + test('positive decimal', function () { + expect(fn('+3.402823466')).toBe(true); + }); + test('positive integer', function () { + expect(fn('+3402823466')).toBe(true); + }); + test('super small negative exponential', function () { + expect(fn('-2.2250738585072014E-308')).toBe(true); + }); + test('hexadecimal', function () { + expect(fn('0x12341')).toBe(true); + }); + test('negative hexadecimal', function () { + expect(fn('-0xaf')).toBe(true); + }); + test('multiple signs', function () { + expect(fn('-+-2')).toBe(true); + }); + test('No decimals for hex', function () { + expect(fn('0x2.2')).toBe(false); + }); + test('Accept a letter for hex', function () { + expect(fn('0xf')).toBe(true); + }); + test('Accept multiple letters for hex', function () { + expect(fn('0xffabc')).toBe(true); + }); + test('Upper case hex', function () { + expect(fn('0xFAFB')).toBe(true); + }); + test('Forbid invalid hex chars', function () { + expect(fn('0xag')).toBe(false); + }); + test('Not matches chars', function () { + expect(fn('abcdef')).toBe(false); + }); + test('pipe seperator', function () { + expect(fn('0123456789|0123456789')).toBe(false); + }); + test('Leading , is not accepted', function () { + expect(fn(',0x12341')).toBe(false); + }); + test('Trailing , is not accepted', function () { + expect(fn('0x12341,')).toBe(false); + }); + } + + describe('validationFunctionForMultipleInt', () => { + const fn = Change.validationFunctionForMultipleInt; + testSingle(fn); + + test('two numbers with leading zeros', function () { + expect(fn('0123456789,0123456789')).toBe(true); + }); + test('negative exponential and decimal with leading zero', function () { + expect(fn('-3.402823466E+38,0123456789')).toBe(true); + }); + test('negative decimal followed by negative exponential', function () { + expect(fn('-3.402823466,-3.402823466E+38')).toBe(true); + }); + test('Multi hex & int', function () { + expect(fn('0xf,0xa,0xb,124')).toBe(true); + }); + test('Forbid invalid hex chars', function () { + expect(fn('0xaf,0xag')).toBe(false); + }); + test('Multi hex more complex', function () { + expect(fn('0xaf,0x0ad')).toBe(true); + }); + test('Space after comma numbers', function () { + expect(fn('1, 2, 3')).toBe(true); + }); + test('Spaces everywhere', function () { + expect(fn(' 1 , 2 , 3 ')).toBe(true); + }); + }); + + describe('validationFunctionForInt', () => { + const fn = Change.validationFunctionForInt; + testSingle(fn); + + test('two numbers', function () { + expect(fn('123,465')).toBe(false); + }); + }); +}); From 293e64b2908972055bc2a27c9daa5da0e1f5b530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sat, 22 Jul 2023 11:42:23 +0200 Subject: [PATCH 2/2] Fix int input validation in Search MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Allow spaces around numbers - Allow plus/minus for hex numbers - Allow multiple plus minus signs for single number - Disallow trailing comma - Disallow arbitrary text before single numbers Signed-off-by: Maximilian Krög --- js/src/table/change.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/table/change.js b/js/src/table/change.js index abca8735690d..b740c670ef7f 100644 --- a/js/src/table/change.js +++ b/js/src/table/change.js @@ -162,7 +162,7 @@ var Change = {}; * @return {boolean} */ Change.validationFunctionForMultipleInt = function (value) { - return value.match(/^(((0x[0-9a-f]+)|([+-]?([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)(e[+-]?[0-9]+)?))(,|$))+$/i) !== null; + return value.split(/\s*,\s*/).every((v) => Change.validationFunctionForInt(v)); }; /** @@ -172,7 +172,7 @@ Change.validationFunctionForMultipleInt = function (value) { * @return {boolean} */ Change.validationFunctionForInt = function (value) { - return value.match(/^(0x[0-9a-f]+$)|([+-]?([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)(e[+-]?[0-9]+)?)$/i) !== null; + return /^\s*([+-]*(0x[0-9a-f]+|([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)(e[+-]?[0-9]+)?))\s*$/i.test(value); }; // used in Search page mostly for INT fields