Bug Summary

File:src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/double.c
Location:line 231, column 9
Description:Potential leak of memory pointed to by 'formatted.bytes'

Annotated Source Code

1#include <assert.h>
2#include <stdlib.h>
3#include <float.h>
4
5#include "xmlrpc-c/util.h"
6#include "xmlrpc-c/util_int.h"
7
8#include "double.h"
9
10typedef struct {
11 char * bytes;
12 char * next;
13 char * end;
14} buffer;
15
16
17static void
18bufferInit(buffer * const bufferP) {
19
20 unsigned int const initialSize = 64;
21
22 bufferP->bytes = malloc(initialSize);
23
24 if (bufferP->bytes) {
25 bufferP->next = bufferP->bytes;
26 bufferP->end = bufferP->bytes + initialSize;
27 }
28}
29
30
31
32static void
33bufferConcat(buffer * const bufferP,
34 char const newChar) {
35
36 if (bufferP->bytes) {
7
Taking true branch
15
Taking true branch
37 if (bufferP->next >= bufferP->end) {
8
Taking true branch
16
Taking true branch
38 size_t const oldSize = bufferP->end - bufferP->bytes;
39 size_t const newSize = oldSize + 64;
40 bufferP->bytes = realloc(bufferP->bytes, newSize);
9
Memory is allocated
17
Attempt to reallocate memory
41 bufferP->next = bufferP->bytes + oldSize;
42 bufferP->end = bufferP->bytes + newSize;
43 }
44
45 if (bufferP->bytes)
10
Taking true branch
18
Reallocation failed
19
Taking false branch
46 *(bufferP->next++) = newChar;
47 }
48}
49
50
51
52static char
53digitChar(unsigned int const digitValue) {
54
55 assert(digitValue < 10)((digitValue < 10) ? (void) (0) : __assert_fail ("digitValue < 10"
, "../../../../libs/xmlrpc-c/src/double.c", 55, __PRETTY_FUNCTION__
))
;
56
57 return '0' + digitValue;
58}
59
60
61
62static unsigned int
63leadDigit(double const arg,
64 double const precision) {
65/*----------------------------------------------------------------------------
66 Assuming 'arg' has one digit before the decimal point (which may be zero),
67 return that digit.
68
69 We assume the precision of 'arg' is plus or minus 'precision', and bias our
70 estimation of the first digit up. We do that bias in order to bias toward
71 shorter decimal ciphers: It's cleaner to consider 2.9999999 to be 3 than to
72 consider 3 to be 2.999999.
73-----------------------------------------------------------------------------*/
74 return MIN(9, (unsigned int)(arg + precision))((9) < ((unsigned int)(arg + precision)) ? (9) : ((unsigned
int)(arg + precision)))
;
75}
76
77
78
79static void
80floatWhole(double const value,
81 buffer * const formattedP,
82 double * const formattedAmountP,
83 double * const precisionP) {
84
85 if (value < 1.0) {
86 /* No digits to add to the whole part */
87 *formattedAmountP = 0;
88 *precisionP = DBL_EPSILON2.2204460492503131e-16;
89 } else {
90 double nonLeastAmount;
91 double nonLeastPrecision;
92 unsigned int leastValue;
93
94 /* Add all digits but the least significant to *formattedP */
95
96 floatWhole(value/10.0, formattedP, &nonLeastAmount,
97 &nonLeastPrecision);
98
99 /* Add the least significant digit to *formattedP */
100
101 if (nonLeastPrecision > 0.1) {
102 /* We're down in the noise now; no point in showing any more
103 significant digits (and we couldn't if we wanted to, because
104 nonLeastPrecision * 10 might be more than 10 less than
105 'value').
106 */
107 leastValue = 0;
108 } else
109 leastValue = leadDigit(value - nonLeastAmount * 10,
110 nonLeastPrecision * 10);
111
112 bufferConcat(formattedP, digitChar(leastValue));
113
114 *formattedAmountP = nonLeastAmount * 10 + leastValue;
115 *precisionP = nonLeastPrecision * 10;
116 }
117}
118
119
120
121static void
122floatFractionPart(double const value,
123 double const wholePrecision,
124 buffer * const formattedP) {
125/*----------------------------------------------------------------------------
126 Serialize the part that comes after the decimal point, assuming there
127 is something (nonzero) before the decimal point that uses up all but
128 'wholePrecision' of the available precision.
129-----------------------------------------------------------------------------*/
130 double precision;
131 double d;
132
133 assert(value < 1.0)((value < 1.0) ? (void) (0) : __assert_fail ("value < 1.0"
, "../../../../libs/xmlrpc-c/src/double.c", 133, __PRETTY_FUNCTION__
))
;
134
135 for (d = value, precision = wholePrecision;
5
Loop condition is true. Entering loop body
12
Loop condition is false. Execution continues on line 136
136 d > precision;
137 precision *= 10) {
138
139 unsigned int digitValue;
140
141 d *= 10;
142 digitValue = leadDigit(d, precision);
143
144 d -= digitValue;
145
146 assert(d < 1.0)((d < 1.0) ? (void) (0) : __assert_fail ("d < 1.0", "../../../../libs/xmlrpc-c/src/double.c"
, 146, __PRETTY_FUNCTION__))
;
147
148 bufferConcat(formattedP, digitChar(digitValue));
6
Calling 'bufferConcat'
11
Returned allocated memory
149 }
150}
151
152
153
154static void
155floatFraction(double const value,
156 buffer * const formattedP) {
157/*----------------------------------------------------------------------------
158 Serialize the part that comes after the decimal point, assuming there
159 is nothing before the decimal point.
160-----------------------------------------------------------------------------*/
161 double precision;
162 double d;
163
164 assert(0.0 < value && value < 1.0)((0.0 < value && value < 1.0) ? (void) (0) : __assert_fail
("0.0 < value && value < 1.0", "../../../../libs/xmlrpc-c/src/double.c"
, 164, __PRETTY_FUNCTION__))
;
165
166 /* Do the leading zeroes, which eat no precision */
167
168 for (d = value * 10; d < 1.0; d *= 10)
169 bufferConcat(formattedP, '0');
170
171 /* Now the significant digits */
172
173 precision = DBL_EPSILON2.2204460492503131e-16;
174
175 while (d > precision) {
176 unsigned int const digitValue = leadDigit(d, precision);
177
178 bufferConcat(formattedP, digitChar(digitValue));
179
180 d -= digitValue;
181
182 assert(d < 1.0)((d < 1.0) ? (void) (0) : __assert_fail ("d < 1.0", "../../../../libs/xmlrpc-c/src/double.c"
, 182, __PRETTY_FUNCTION__))
;
183
184 d *= 10;
185 precision *= 10;
186 }
187}
188
189
190
191void
192xmlrpc_formatFloat(xmlrpc_env * const envP,
193 double const value,
194 const char ** const formattedP) {
195
196 double absvalue;
197 buffer formatted;
198
199 bufferInit(&formatted);
200
201 if (value < 0.0) {
1
Taking false branch
202 bufferConcat(&formatted, '-');
203 absvalue = - value;
204 } else
205 absvalue = value;
206
207 if (absvalue >= 1.0) {
2
Taking true branch
208 double wholePart, fractionPart;
209 double wholePrecision;
210
211 floatWhole(absvalue, &formatted, &wholePart, &wholePrecision);
212
213 fractionPart = absvalue - wholePart;
214
215 if (fractionPart > wholePrecision) {
3
Taking true branch
216 bufferConcat(&formatted, '.');
217
218 floatFractionPart(fractionPart, wholePrecision, &formatted);
4
Calling 'floatFractionPart'
13
Returned allocated memory
219 }
220 } else {
221 bufferConcat(&formatted, '0');
222
223 if (absvalue > 0.0) {
224 bufferConcat(&formatted, '.');
225 floatFraction(absvalue, &formatted);
226 }
227 }
228 bufferConcat(&formatted, '\0');
14
Calling 'bufferConcat'
20
Reallocation failed
229
230 if (formatted.bytes == NULL((void*)0))
21
Taking true branch
231 xmlrpc_faultf(envP, "Couldn't allocate memory to format %g", value);
22
Potential leak of memory pointed to by 'formatted.bytes'
232 else
233 *formattedP = formatted.bytes;
234}