From 378043f104daeee4e48a8e99c13db4bda4650721 Mon Sep 17 00:00:00 2001 From: dualfroz Date: Thu, 3 Sep 2026 14:09:51 +0200 Subject: [PATCH] fix(dynamic-typing): accept an explicit leading plus sign on numbers The FLOAT gate in testFloat allowed only a minus sign on the mantissa, while the exponent right after it already allowed either sign. dynamicTyping therefore left +42 and +1.5E-03 as strings and converted -42 and -1.5E-03, silently producing columns that mix numbers and strings depending on how each row wrote its sign. parseFloat already accepts a leading plus and returns the right value, so the regex was stricter than the conversion it guards. Allow either sign on the mantissa, matching the exponent. The 2^53 precision guard is unchanged, and a plus that is not a sign is still rejected. Fixes #1070 --- papaparse.js | 2 +- tests/test-cases.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/papaparse.js b/papaparse.js index 5229936..1aa8a58 100644 --- a/papaparse.js +++ b/papaparse.js @@ -966,7 +966,7 @@ License: MIT // One goal is to minimize the use of regular expressions... var MAX_FLOAT = Math.pow(2, 53); var MIN_FLOAT = -MAX_FLOAT; - var FLOAT = /^\s*-?(\d+\.?|\.\d+|\d+\.\d+)([eE][-+]?\d+)?\s*$/; + var FLOAT = /^\s*[-+]?(\d+\.?|\.\d+|\d+\.\d+)([eE][-+]?\d+)?\s*$/; var ISO_DATE = /^((\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)))$/; var self = this; var _stepCounter = 0; // Number of times step was called (number of rows parsed) diff --git a/tests/test-cases.js b/tests/test-cases.js index 72c540a..514b9d2 100644 --- a/tests/test-cases.js +++ b/tests/test-cases.js @@ -932,6 +932,24 @@ var PARSE_TESTS = [ errors: [] } }, + { + description: "Dynamic typing converts numeric literals with an explicit plus sign", + input: '+1,+2.2,+1e3\r\n+4,+4.5,+1.5E-03\r\n+.5,+9007199254740991,+9007199254740992', + config: { dynamicTyping: true }, + expected: { + data: [[1, 2.2, 1000], [4, 4.5, 0.0015], [0.5, 9007199254740991, "+9007199254740992"]], + errors: [] + } + }, + { + description: "Dynamic typing doesn't convert a plus sign that isn't a sign", + input: '+,++1,+-1\r\n+a,1+2,+ 1', + config: { dynamicTyping: true }, + expected: { + data: [["+", "++1", "+-1"], ["+a", "1+2", "+ 1"]], + errors: [] + } + }, { description: "Dynamic typing converts boolean literals", input: 'true,false,T,F,TRUE,FALSE,True,False',