Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a75a418

Browse files
committed
Clean up dubious code in contrib/seg.
The restore() function assumed that the result of sprintf() with %e format would necessarily contain an 'e', which is false: what if the supplied number is an infinity or NaN? If that did happen, we'd get a null-pointer-dereference core dump. The case appears impossible currently, because seg_in() does not accept such values, and there are no seg-creating functions that would create one. But it seems unwise to rely on it never happening in future. Quite aside from that, the code was pretty ugly: it relied on modifying a static format string when it could use a "*" precision argument, and it used strtok() entirely gratuitously, and it stripped off trailing spaces by hand instead of just not asking for them to begin with. Coverity noticed the potential null pointer dereference (though I wonder why it didn't complain years ago, since this code is ancient). Since this is just code cleanup and forestalling a hypothetical future bug, there seems no need for back-patching.
1 parent 8f75fd1 commit a75a418

File tree

1 file changed

+19
-19
lines changed

1 file changed

+19
-19
lines changed

contrib/seg/seg.c

+19-19
Original file line numberDiff line numberDiff line change
@@ -833,15 +833,18 @@ seg_different(SEG *a, SEG *b)
833833
* Auxiliary functions
834834
*****************************************************************************/
835835

836-
/* The purpose of this routine is to print the floating point
837-
* value with exact number of significant digits. Its behaviour
836+
/*
837+
* The purpose of this routine is to print the given floating point
838+
* value with exactly n significant digits. Its behaviour
838839
* is similar to %.ng except it prints 8.00 where %.ng would
839-
* print 8
840+
* print 8. Returns the length of the string written at "result".
841+
*
842+
* Caller must provide a sufficiently large result buffer; 16 bytes
843+
* should be enough for all known float implementations.
840844
*/
841845
static int
842846
restore(char *result, float val, int n)
843847
{
844-
static char efmt[8] = {'%', '-', '1', '5', '.', '#', 'e', 0};
845848
char buf[25] = {
846849
'0', '0', '0', '0', '0',
847850
'0', '0', '0', '0', '0',
@@ -856,32 +859,29 @@ restore(char *result, float val, int n)
856859
sign;
857860

858861
/*
859-
* put a cap on the number of siugnificant digits to avoid nonsense in the
860-
* output
862+
* Put a cap on the number of significant digits to avoid garbage in the
863+
* output and ensure we don't overrun the result buffer.
861864
*/
862865
n = Min(n, FLT_DIG);
863866

864867
/* remember the sign */
865868
sign = (val < 0 ? 1 : 0);
866869

867-
efmt[5] = '0' + (n - 1) % 10; /* makes %-15.(n-1)e -- this format
868-
* guarantees that the exponent is
869-
* always present */
870-
871-
sprintf(result, efmt, val);
870+
/* print, in %e style to start with */
871+
sprintf(result, "%.*e", n - 1, val);
872872

873-
/* trim the spaces left by the %e */
874-
for (p = result; *p != ' '; p++);
875-
*p = '\0';
873+
/* find the exponent */
874+
p = strchr(result, 'e');
876875

877-
/* get the exponent */
878-
strtok(pstrdup(result), "e");
879-
exp = atoi(strtok(NULL, "e"));
876+
/* punt if we have 'inf' or similar */
877+
if (p == NULL)
878+
return strlen(result);
880879

880+
exp = atoi(p + 1);
881881
if (exp == 0)
882882
{
883-
/* use the supplied mantyssa with sign */
884-
strcpy((char *) strchr(result, 'e'), "");
883+
/* just truncate off the 'e+00' */
884+
*p = '\0';
885885
}
886886
else
887887
{

0 commit comments

Comments
 (0)