Tcl Library Source Code

View Ticket
Login
Ticket UUID: c974e352d2fdc34a8d267cd23c4a76a779770b4d
Title: Invalid float parsing in json2dict
Type: Bug Version: 1.18
Submitter: pda Created on: 2017-03-27 11:42:41
Subsystem: json Assigned To: aku
Priority: 7 High Severity: Severe
Status: Closed Last Modified: 2017-05-29 22:26:11
Resolution: Fixed Closed By: aku
    Closed on: 2017-05-29 22:26:11
Description:
json2dict accept an invalid floating point number:

% package require json
1.3.3
% json::json2dict .1
1

According to json.org, a number cannot start with a decimal point (0.1 is valid, .1 is not).
User Comments: aku added on 2017-05-29 22:26:11:

Fix merged with commit [dbdaf3dff4].

Version bumped to 1.3.4

Extended testsuite.

Went with additional number patterns. Essentially when parts of the number are missing other parts become mandatory, and that was not handled by the existing single pattern for numbers.

Thank you for the report, and your patience.


aku added on 2017-05-29 22:06:43:

The conversion issue affects only the Tcl implementation. The Critcl implementation converts correctly.

... It is something in the RE to split the json into tokens. ... Deeper, something in the "json::numberRE".

Test script:

lappend auto_path [pwd]

puts [package require json]=[package ifneeded json [package require json]] puts [info patchlevel] puts *\t[join [info loaded] \n*\t]

puts "" foreach {fp} { 1.1 0.1 .1 1. 1 } { set m [regexp -- $json::numberRE $fp match] regexp -indices -- $json::numberRE $fp matchi

puts ($fp):\t${m}\t[json::json2dict $fp]\t($match)\t($matchi) }

Results:

1.3.3=source /home/aku/Play/Tcllib/dev.tcllib/modules/json/json.tcl
8.5.18
*

(1.1): 1 1.1 (1.1) (0 2) (0.1): 1 0.1 (0.1) (0 2) (.1): 1 1 (1) (1 1) *** (1.): 1 1 (1) (0 0) (1): 1 1 (1) (0 0)


The .1 is interesting, see ***. It matches only "1", ignoring the leading dot.

The relevant code in the package is

proc ::json::json2dict_tcl {jsonText} {
    variable tokenRE
    set tokens [regexp -all -inline -- $tokenRE $jsonText]  
[...]
where numberRE is an alternative in tokenRE.

With the given input it will also ignore leading dot.

Part of the problem is that the pattern is not anchored. However because the code uses -all it cannot be anchored, doing so would prevent the matches after the first token.

And do not forget that the trailing dot for "1." is ignored as well.

I might have to create specialized number patterns for these cases to get them matched correctly. (I.e. patterns for fractionals, and cardinal with trailing dot, but no fractional)


aku added on 2017-05-29 21:15:26:
To me the issue is less that the 0.1 is accepted (because it simply is a superset of the spec) and more that it is converted incorrectly. That is a problem.

Of course, if the easy fix is to disallow the form of input I will likely go for that. But we will see.