-
Notifications
You must be signed in to change notification settings - Fork 146
Open
Description
In SLEEF 4.0, Sleef_strtoq has a regression compared to version 3.8. The function no longer correctly sets endptr to indicate where parsing stopped, and it incorrectly parses past whitespace and other delimiters (like commas), which violates the expected behavior of strtod-like functions.
Expected Behavior
Sleef_strtoq should behave like the standard strtod function:
endptrshould point to the first character that could not be parsed- Parsing should stop at whitespace, commas, letters, or any non-numeric character that isn't part of a valid floating-point representation
Actual Behavior in SLEEF 4.0
endptris always set to the end of the string (empty string""), regardless of where parsing actually stopped- The function ignores whitespace and comma delimiters, continuing to parse characters that should stop parsing
- This makes it impossible to detect parse failures or determine where valid input ends
Reproduction
Details
#include <iostream>
#include <iomanip>
#include <sleefquad.h>
#include <cmath>
#include <cstdlib>
int main()
{
// Test strtoq with invalid strings
char *endptr = NULL;
char *endptr_d = NULL;
// Test 1: "abc"
endptr = NULL;
endptr_d = NULL;
Sleef_quad q1 = Sleef_strtoq("abc", &endptr);
double d1 = strtod("abc", &endptr_d);
std::cout << "Input: 'abc'" << std::endl;
std::cout << " [strtoq] endptr: '" << (endptr ? endptr : "NULL") << "'" << std::endl;
Sleef_printf(" [strtoq] value: %.6Qe\n", q1);
std::cout << " [strtod] endptr: '" << (endptr_d ? endptr_d : "NULL") << "'" << std::endl;
std::cout << " [strtod] value: " << std::scientific << std::setprecision(6) << d1 << std::endl;
std::cout << std::endl;
// Test 2: "1.23abc"
endptr = NULL;
endptr_d = NULL;
Sleef_quad q2 = Sleef_strtoq("1.23abc", &endptr);
double d2 = strtod("1.23abc", &endptr_d);
std::cout << "Input: '1.23abc'" << std::endl;
std::cout << " [strtoq] endptr: '" << (endptr ? endptr : "NULL") << "'" << std::endl;
Sleef_printf(" [strtoq] value: %.6Qe\n", q2);
std::cout << " [strtod] endptr: '" << (endptr_d ? endptr_d : "NULL") << "'" << std::endl;
std::cout << " [strtod] value: " << std::scientific << std::setprecision(6) << d2 << std::endl;
std::cout << std::endl;
// Test 3: "1.23"
endptr = NULL;
endptr_d = NULL;
Sleef_quad q3 = Sleef_strtoq("1.23", &endptr);
double d3 = strtod("1.23", &endptr_d);
std::cout << "Input: '1.23'" << std::endl;
std::cout << " [strtoq] endptr: '" << (endptr ? endptr : "NULL") << "'" << std::endl;
Sleef_printf(" [strtoq] value: %.6Qe\n", q3);
std::cout << " [strtod] endptr: '" << (endptr_d ? endptr_d : "NULL") << "'" << std::endl;
std::cout << " [strtod] value: " << std::scientific << std::setprecision(6) << d3 << std::endl;
std::cout << std::endl;
// Test 4: "1.23 456" - whitespace delimiter test
endptr = NULL;
endptr_d = NULL;
Sleef_quad q4 = Sleef_strtoq("1.23 456", &endptr);
double d4 = strtod("1.23 456", &endptr_d);
std::cout << "Input: '1.23 456'" << std::endl;
std::cout << " [strtoq] endptr: '" << (endptr ? endptr : "NULL") << "'" << std::endl;
Sleef_printf(" [strtoq] value: %.6Qe\n", q4);
std::cout << " [strtod] endptr: '" << (endptr_d ? endptr_d : "NULL") << "'" << std::endl;
std::cout << " [strtod] value: " << std::scientific << std::setprecision(6) << d4 << std::endl;
std::cout << std::endl;
// Test 5: "1.23,456" - comma delimiter test
endptr = NULL;
endptr_d = NULL;
Sleef_quad q5 = Sleef_strtoq("1.23,456", &endptr);
double d5 = strtod("1.23,456", &endptr_d);
std::cout << "Input: '1.23,456'" << std::endl;
std::cout << " [strtoq] endptr: '" << (endptr ? endptr : "NULL") << "'" << std::endl;
Sleef_printf(" [strtoq] value: %.6Qe\n", q5);
std::cout << " [strtod] endptr: '" << (endptr_d ? endptr_d : "NULL") << "'" << std::endl;
std::cout << " [strtod] value: " << std::scientific << std::setprecision(6) << d5 << std::endl;
std::cout << std::endl;
// Test 6: " 1.23 " - leading/trailing whitespace
endptr = NULL;
endptr_d = NULL;
Sleef_quad q6 = Sleef_strtoq(" 1.23 ", &endptr);
double d6 = strtod(" 1.23 ", &endptr_d);
std::cout << "Input: ' 1.23 '" << std::endl;
std::cout << " [strtoq] endptr: '" << (endptr ? endptr : "NULL") << "'" << std::endl;
Sleef_printf(" [strtoq] value: %.6Qe\n", q6);
std::cout << " [strtod] endptr: '" << (endptr_d ? endptr_d : "NULL") << "'" << std::endl;
std::cout << " [strtod] value: " << std::scientific << std::setprecision(6) << d6 << std::endl;
return 0;
}Results
SLEEF 3.8 (Correct behavior, matches strtod):
Input: 'abc'
[strtoq] endptr: 'abc'
[strtoq] value: 0.000000e+00
[strtod] endptr: 'abc'
[strtod] value: 0.000000e+00
Input: '1.23abc'
[strtoq] endptr: 'abc'
[strtoq] value: 1.230000e+00
[strtod] endptr: 'abc'
[strtod] value: 1.230000e+00
Input: '1.23'
[strtoq] endptr: ''
[strtoq] value: 1.230000e+00
[strtod] endptr: ''
[strtod] value: 1.230000e+00
Input: '1.23 456'
[strtoq] endptr: ' 456'
[strtoq] value: 1.230000e+00
[strtod] endptr: ' 456'
[strtod] value: 1.230000e+00
Input: '1.23,456'
[strtoq] endptr: ',456'
[strtoq] value: 1.230000e+00
[strtod] endptr: ',456'
[strtod] value: 1.230000e+00
Input: ' 1.23 '
[strtoq] endptr: ' '
[strtoq] value: 1.230000e+00
[strtod] endptr: ' '
[strtod] value: 1.230000e+00
SLEEF 4.0 (Broken behavior):
Input: 'abc'
[strtoq] endptr: ''
[strtoq] value: 0.000000e+00
[strtod] endptr: 'abc'
[strtod] value: 0.000000e+00
Input: '1.23abc'
[strtoq] endptr: ''
[strtoq] value: 1.230000e+00
[strtod] endptr: 'abc'
[strtod] value: 1.230000e+00
Input: '1.23'
[strtoq] endptr: ''
[strtoq] value: 1.230000e+00
[strtod] endptr: ''
[strtod] value: 1.230000e+00
Input: '1.23 456'
[strtoq] endptr: ''
[strtoq] value: 1.234560e+00
[strtod] endptr: ' 456'
[strtod] value: 1.230000e+00
Input: '1.23,456'
[strtoq] endptr: ''
[strtoq] value: 1.234560e+00
[strtod] endptr: ',456'
[strtod] value: 1.230000e+00
Input: ' 1.23 '
[strtoq] endptr: ''
[strtoq] value: 1.230000e+00
[strtod] endptr: ' '
[strtod] value: 1.230000e+00
Environment
- SLEEF version: 4.0 and 3.8
- Platform: macOS (arm64)
- Compiler: Apple clang
Metadata
Metadata
Assignees
Labels
No labels