Bug Summary

File:FreeType/xttcap.c
Location:line 668, column 17
Description:Potential leak of memory pointed to by 'duplicated'

Annotated Source Code

1/* ===EmacsMode: -*- Mode: C; tab-width:4; c-basic-offset: 4; -*- === */
2/* ===FileName: ===
3 Copyright (c) 1998 Takuya SHIOZAKI, All Rights reserved.
4 Copyright (c) 1998 X-TrueType Server Project, All rights reserved.
5 Copyright (c) 2003 After X-TT Project, All rights reserved.
6
7===Notice
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16
17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 SUCH DAMAGE.
28
29 Major Release ID: X-TrueType Server Version 1.4 [Charles's Wain Release 0]
30
31Notice===
32 */
33
34/*
35#include "xttversion.h"
36
37static char const * const releaseID =
38 _XTT_RELEASE_NAME;
39*/
40
41#ifdef HAVE_CONFIG_H1
42#include <config.h>
43#endif
44#include "libxfontint.h"
45#include <X11/fonts/fontmisc.h>
46#include <string.h>
47#include <ctype.h>
48#include <math.h>
49
50#ifndef True(-1)
51#define True(-1) (-1)
52#endif /* True */
53#ifndef False(0)
54#define False(0) (0)
55#endif /* False */
56
57#include "xttcap.h"
58
59
60/**************************************************************************
61 Private Data Types
62 */
63
64/* Property Record List */
65/* List Node */
66typedef struct TagSPropRecValListNodeP
67{
68 SPropRecValContainerEntityP containerE;
69 struct TagSPropRecValListNodeP *nextNode;
70} SPropRecValListNodeP;
71
72
73/**************************************************************************
74 Tables
75 */
76
77/* valid record field */
78static SPropertyRecord const validRecords[] =
79{
80 { "FontFile", eRecTypeString },
81 { "FaceNumber", eRecTypeString },
82 { "AutoItalic", eRecTypeDouble },
83 { "DoubleStrike", eRecTypeString },
84 { "FontProperties", eRecTypeBool },
85 { "ForceSpacing", eRecTypeString },
86 { "ScaleBBoxWidth", eRecTypeString },
87 { "ScaleWidth", eRecTypeDouble },
88 { "EncodingOptions", eRecTypeString },
89 { "Hinting", eRecTypeBool },
90 { "VeryLazyMetrics", eRecTypeBool },
91 { "CodeRange", eRecTypeString },
92 { "EmbeddedBitmap", eRecTypeString },
93 { "VeryLazyBitmapWidthScale", eRecTypeDouble },
94 { "ForceConstantSpacingCodeRange", eRecTypeString },
95 { "ForceConstantSpacingMetrics", eRecTypeString },
96 { "Dummy", eRecTypeVoid }
97};
98static int const
99numOfValidRecords = sizeof(validRecords)/sizeof(validRecords[0]);
100
101/* correspondence between record name and cap variable name */
102static struct {
103 char const * capVariable;
104 char const * recordName;
105} const correspondRelations[] = {
106 { "fn", "FaceNumber" },
107 { "ai", "AutoItalic" },
108 { "ds", "DoubleStrike" },
109 { "fp", "FontProperties" },
110 { "fs", "ForceSpacing" },
111 { "bw", "ScaleBBoxWidth" },
112 { "sw", "ScaleWidth" },
113 { "eo", "EncodingOptions" },
114 { "vl", "VeryLazyMetrics" },
115 { "bs", "VeryLazyBitmapWidthScale" },
116 { "cr", "CodeRange" },
117 { "eb", "EmbeddedBitmap" },
118 { "hi", "Hinting" },
119 { "fc", "ForceConstantSpacingCodeRange" },
120 { "fm", "ForceConstantSpacingMetrics" }
121};
122static int const
123numOfCorrespondRelations
124= sizeof(correspondRelations)/sizeof(correspondRelations[0]);
125
126/**************************************************************************
127 Functions
128 */
129
130/* get property record type by record name */
131static Bool /* True == Found, False == Not Found */
132get_record_type_by_name(SPropertyRecord const ** const refRefRecord, /*result*/
133 char const *strName)
134{
135 Bool result = False(0);
136 int i;
137
138 *refRefRecord = NULL((void *)0);
139 for (i=0; i<numOfValidRecords; i++) {
140 if (!strcasecmp(validRecords[i].strRecordName, strName)) {
141 result = True(-1);
142 *refRefRecord = &validRecords[i];
143 break;
144 }
145 }
146
147 return result;
148}
149
150/* Add Property Record Value */
151static Bool /* True == Error, False == Success */
152SPropRecValList_add_record(SDynPropRecValList *pThisList,
153 char const * const recordName,
154 char const * const strValue)
155{
156 Bool result = False(0);
157 SPropRecValContainerEntityP tmpContainerE;
158
159 if (get_record_type_by_name(&tmpContainerE.refRecordType, recordName)) {
160 switch (tmpContainerE.refRecordType->recordType) {
161 case eRecTypeInteger:
162 {
163 int val;
164 char *endPtr;
165
166 val = strtol(strValue, &endPtr, 0);
167 if ('\0' != *endPtr) {
168 fprintf(stderr__stderrp,
169 "truetype font property : "
170 "%s record needs integer value.\n",
171 recordName);
172 result = True(-1);
173 goto quit;
174 }
175 SPropContainer_value_int(&tmpContainerE)((&tmpContainerE)->uValue.integerValue) = val;
176 }
177 break;
178 case eRecTypeDouble:
179 {
180 double val;
181 char *endPtr;
182
183 val = strtod(strValue, &endPtr);
184 if ('\0' != *endPtr) {
185 fprintf(stderr__stderrp,
186 "truetype font property : "
187 "%s record needs floating point value.\n",
188 recordName);
189 result = True(-1);
190 goto quit;
191 }
192 SPropContainer_value_dbl(&tmpContainerE)((&tmpContainerE)->uValue.doubleValue) = val;
193 }
194 break;
195 case eRecTypeBool:
196 {
197 Bool val;
198
199 if (!strcasecmp(strValue, "yes"))
200 val = True(-1);
201 else if (!strcasecmp(strValue, "y"))
202 val = True(-1);
203 else if (!strcasecmp(strValue, "on"))
204 val = True(-1);
205 else if (!strcasecmp(strValue, "true"))
206 val = True(-1);
207 else if (!strcasecmp(strValue, "t"))
208 val = True(-1);
209 else if (!strcasecmp(strValue, "ok"))
210 val = True(-1);
211 else if (!strcasecmp(strValue, "no"))
212 val = False(0);
213 else if (!strcasecmp(strValue, "n"))
214 val = False(0);
215 else if (!strcasecmp(strValue, "off"))
216 val = False(0);
217 else if (!strcasecmp(strValue, "false"))
218 val = False(0);
219 else if (!strcasecmp(strValue, "f"))
220 val = False(0);
221 else if (!strcasecmp(strValue, "bad"))
222 val = False(0);
223 else {
224 fprintf(stderr__stderrp,
225 "truetype font property : "
226 "%s record needs boolean value.\n",
227 recordName);
228 result = True(-1);
229 goto quit;
230 }
231 SPropContainer_value_bool(&tmpContainerE)((&tmpContainerE)->uValue.boolValue) = val;
232 }
233 break;
234 case eRecTypeString:
235 {
236 char *p;
237
238 if (NULL((void *)0) == (p = strdup(strValue))) {
239 fprintf(stderr__stderrp,
240 "truetype font property : "
241 "cannot allocate memory.\n");
242 result = True(-1);
243 goto quit;
244 }
245 SPropContainer_value_str(&tmpContainerE)((&tmpContainerE)->uValue.dynStringValue) = p;
246 }
247 break;
248 case eRecTypeVoid:
249 if ('\0' != *strValue) {
250 fprintf(stderr__stderrp,
251 "truetype font property : "
252 "%s record needs void.\n", recordName);
253 result = True(-1);
254 }
255 break;
256 }
257 {
258 /* add to list */
259 SPropRecValListNodeP *newNode;
260
261 if (NULL((void *)0) == (newNode = malloc(sizeof(*newNode)))) {
262 fprintf(stderr__stderrp,
263 "truetype font property : "
264 "cannot allocate memory.\n");
265 result = True(-1);
266 goto quit;
267 }
268 newNode->nextNode = pThisList->headNode;
269 newNode->containerE = tmpContainerE;
270 tmpContainerE.refRecordType = NULL((void *)0); /* invalidate --
271 disown value handle. */
272 pThisList->headNode = newNode;
273 }
274 } else {
275 /* invalid record name */
276 fprintf(stderr__stderrp,
277 "truetype font : "
278 "invalid record name \"%s.\"\n", recordName);
279 result = True(-1);
280 }
281
282 quit:
283 return result;
284}
285
286#ifdef USE_TTP_FILE
287
288#ifndef LEN_LINEBUF
289#define LEN_LINEBUF 2048
290#endif /* !def LEN_LINEBUF */
291
292/* get one line */
293static Bool /* True == Error, False == Success */
294get_one_line(FILE *is, char *buf)
295{
296 Bool result = False(0);
297 int count = 0;
298 Bool flHead = True(-1);
299 Bool flSpace = False(0);
300 Bool flInSingleQuote = False(0);
301 Bool flInDoubleQuote = False(0);
302 Bool flBackSlash = False(0);
303 Bool flFirstElement = True(-1);
304
305 *buf = '\0';
306 for (;;) {
307 int c = fgetc(is);
308
309 if (ferror(is)) {
310 fprintf(stderr__stderrp, "truetype font property file : read error.\n");
311 result = True(-1);
312 break;
313 }
314
315 if (EOF(-1) == c) {
316 if (flInSingleQuote || flInDoubleQuote) {
317 fprintf(stderr__stderrp,
318 "truetype font property file : unmatched quote.\n");
319 result = True(-1);
320 }
321 break;
322 }
323 if (flInSingleQuote) {
324 if ('\'' == c) {
325 /* end of single quoted string */
326 flInSingleQuote = False(0);
327 c = -1; /* NOT extract to buffer. */
328 } else
329 /* others, extract all character to buffer unconditionally. */
330 ;
331 goto trans;
332 }
333 if (flBackSlash) {
334 /* escape --- when just before character is backslash,
335 next character is escaped. */
336 flBackSlash = False(0);
337 if ('n' == c)
338 /* newline */
339 c = '\n';
340 if ('\n' == c)
341 /* ignore newline */
342 c = -1;
343 else
344 /* others, extract all character to buffer unconditionally. */
345 ;
346 goto trans;
347 }
348 if ('\\' == c) {
349 /* set flag to escape next character. */
350 flBackSlash = True(-1);
351 c = -1; /* NOT extract to buffer. */
352 goto trans;
353 }
354 if (flInDoubleQuote) {
355 if ('"' == c) {
356 /* end of double quoted string */
357 flInDoubleQuote = False(0);
358 c = -1; /* NOT extract to buffer. */
359 } else
360 /* others, extract all character to buffer unconditionally. */
361 ;
362 goto trans;
363 }
364 if ('#' == c) {
365 /* skip comment till end of line. */
366 while ('\n' != c) {
367 c = fgetc(is);
368 if (ferror(is)) {
369 fprintf(stderr__stderrp,
370 "truetype font property file : read error.\n");
371 result = True(-1);
372 break;
373 }
374 if (EOF(-1) == c) {
375 break;
376 }
377 }
378 break;
379 }
380 if ('\'' == c) {
381 /* into single quoted string */
382 flInSingleQuote = True(-1);
383 c = -1; /* NOT extract to buffer. */
384 goto trans;
385 }
386 if ('"' == c) {
387 /* into double quoted string */
388 flInDoubleQuote = True(-1);
389 c = -1; /* NOT extract to buffer. */
390 goto trans;
391 }
392 if ('\n' == c)
393 /* End of Line */
394 break;
395 if (isspace(c)) {
396 /* convine multiple spaces */
397 if (!flHead)
398 /* except space at the head of line */
399 flSpace = True(-1);
400 continue;
401 }
402 trans:
403 /* set flHead to False, since current character is not white space
404 when reaches here. */
405 flHead = False(0);
406 do {
407 if (count>=LEN_LINEBUF-1) {
408 /* overflow */
409 fprintf(stderr__stderrp,
410 "truetype font property file : too long line.\n");
411 result = True(-1);
412 goto quit;
413 }
414 if (flSpace) {
415 /* just before characters is white space, but
416 current character is not WS. */
417 if (flFirstElement) {
418 /* this spaces is the first cell(?) of white spaces. */
419 flFirstElement = False(0);
420 /* separate record name and record value */
421 *buf = (char)0xff;
422 } else
423 *buf = ' ';
424 flSpace = False(0);
425 } else
426 if (-1 != c) {
427 *buf = c;
428 c = -1; /* invalidate */
429 } else
430 /* skip */
431 buf--;
432 buf++;
433 } while (-1 != c); /* when 'c' is not -1, it means
434 that 'c' contains an untreated character. */
435 }
436 *buf = '\0';
437
438 quit:
439 return result;
440}
441
442/* parse one line */
443static Bool /* True == Error, False == Success */
444parse_one_line(SDynPropRecValList *pThisList, FILE *is)
445{
446 Bool result = False(0);
447 char *buf = NULL((void *)0);
448 char *recordHead, *valueHead = NULL((void *)0);
449
450 if (NULL((void *)0) == (buf = malloc(LEN_LINEBUF))) {
451 fprintf(stderr__stderrp,
452 "truetype font property file : cannot allocate memory.\n");
453 result = True(-1);
454 goto abort;
455 }
456 {
457 recordHead = buf;
458/* refRecordValue->refRecordType = NULL;*/
459 do {
460 if (get_one_line(is, buf)) {
461 result = True(-1);
462 goto quit;
463 }
464 if (feof(is)) {
465 if ('\0' == *buf)
466 goto quit;
467 break;
468 }
469 } while ('\0' == *buf);
470
471 if (NULL((void *)0) != (valueHead = strchr(buf, 0xff))) {
472 *valueHead = '\0';
473 valueHead++;
474 } else
475 valueHead = buf+strlen(buf);
476#if 0
477 fprintf(stderr__stderrp,
478 "truetype font property file : \n"
479 "recName:\"%s\"\nvalue:\"%s\"\n",
480 recordHead, valueHead);
481#endif
482 result = SPropRecValList_add_record(pThisList, recordHead, valueHead);
483 }
484 quit:
485 free(buf);
486 abort:
487 return result;
488}
489
490/* Read Property File */
491Bool /* True == Error, False == Success */
492SPropRecValList_read_prop_file(SDynPropRecValList *pThisList,
493 char const * const strFileName)
494{
495 Bool result = False(0);
496 FILE *is;
497
498#if 1
499 if (!strcmp(strFileName, "-"))
500 is = stdin__stdinp;
501 else
502#endif
503 is = fopen(strFileName, "r");
504 if (NULL((void *)0) == is) {
505 fprintf(stderr__stderrp, "truetype font property : cannot open file %s.\n",
506 strFileName);
507 result = True(-1);
508 goto abort;
509 }
510 {
511 for (;;) {
512 if (False(0) != (result = parse_one_line(pThisList, is)))
513 goto quit;
514 if (feof(is))
515 break;
516 }
517 }
518 quit:
519#if 1
520 if (strcmp(strFileName, "-"))
521#endif
522 fclose(is);
523 abort:
524 return result;
525}
526#endif /* USE_TTP_FILE */
527
528/* Constructor for Container Node */
529Bool /* True == Error, False == Success */
530SPropRecValList_new(SDynPropRecValList *pThisList)
531{
532 Bool result = False(0);
533
534 pThisList->headNode = NULL((void *)0);
535
536 return result;
537}
538
539#ifdef DUMP
540void
541SPropRecValList_dump(SRefPropRecValList *pThisList)
542{
543 SPropRecValListNodeP *p;
544 for (p=pThisList->headNode; NULL((void *)0)!=p; p=p->nextNode) {
545 switch (p->containerE.refRecordType->recordType) {
546 case eRecTypeInteger:
547 fprintf(stderr__stderrp, "%s = %d\n",
548 p->containerE.refRecordType->strRecordName,
549 p->containerE.uValue.integerValue);
550 break;
551 case eRecTypeDouble:
552 fprintf(stderr__stderrp, "%s = %f\n",
553 p->containerE.refRecordType->strRecordName,
554 p->containerE.uValue.doubleValue);
555 break;
556 case eRecTypeBool:
557 fprintf(stderr__stderrp, "%s = %s\n",
558 p->containerE.refRecordType->strRecordName,
559 p->containerE.uValue.boolValue
560 ? "True":"False");
561 break;
562 case eRecTypeString:
563 fprintf(stderr__stderrp, "%s = \"%s\"\n",
564 p->containerE.refRecordType->strRecordName,
565 p->containerE.uValue.dynStringValue);
566 break;
567 case eRecTypeVoid:
568 fprintf(stderr__stderrp, "%s = void\n",
569 p->containerE.refRecordType->strRecordName);
570 break;
571 }
572 }
573}
574#endif
575
576
577/* Search Property Record */
578Bool /* True == Hit, False == Miss */
579SPropRecValList_search_record(SRefPropRecValList *pThisList,
580 SPropRecValContainer *refRecValue,
581 char const * const recordName)
582{
583 Bool result = False(0);
584 SPropRecValListNodeP *p;
585
586 *refRecValue = NULL((void *)0);
587 for (p=pThisList->headNode; NULL((void *)0)!=p; p=p->nextNode) {
588 if (!strcasecmp(p->containerE.refRecordType->strRecordName,
589 recordName)) {
590 *refRecValue = &p->containerE;
591 result = True(-1);
592 break;
593 }
594 }
595
596 return result;
597}
598
599
600/* Parse TTCap */
601Bool /* True == Error, False == Success */
602SPropRecValList_add_by_font_cap(SDynPropRecValList *pThisList,
603 char const *strCapHead)
604{
605 Bool result = False(0);
606 /* SPropertyRecord const *refRecordType; */
607 char const *term;
608
609 if (NULL((void *)0) == (term = strrchr(strCapHead, ':')))
1
Taking false branch
610 goto abort;
611
612 {
613 /* for xfsft compatible */
614 char const *p;
615 for (p=term-1; p>=strCapHead; p--) {
2
Loop condition is false. Execution continues on line 641
616 if ( ':'==*p ) {
617 /*
618 * :num:filename
619 * ^p ^term
620 */
621 if ( p!=term ) {
622 int len = term-p-1;
623 char *value;
624
625 value=malloc(len+1);
626 memcpy(value, p+1, len)__builtin___memcpy_chk (value, p+1, len, __builtin_object_size
(value, 0))
;
627 value[len]='\0';
628 SPropRecValList_add_record(pThisList,
629 "FaceNumber",
630 value);
631 free(value);
632 term=p;
633 }
634 break;
635 }
636 if ( !isdigit((unsigned char)*p) )
637 break;
638 }
639 }
640
641 while (strCapHead<term) {
3
Assuming 'strCapHead' is < 'term'
4
Loop condition is true. Entering loop body
642 int i;
643 char const *nextColon = strchr(strCapHead, ':');
644 if (0<nextColon-strCapHead) {
5
Taking true branch
645 char *duplicated = malloc((nextColon-strCapHead)+1);
6
Memory is allocated
646 {
647 char *value;
648
649 memcpy(duplicated, strCapHead, nextColon-strCapHead)__builtin___memcpy_chk (duplicated, strCapHead, nextColon-strCapHead
, __builtin_object_size (duplicated, 0))
;
650 duplicated[nextColon-strCapHead] = '\0';
651 if (NULL((void *)0) != (value=strchr(duplicated, '='))) {
7
Taking true branch
652 *value = '\0';
653 value++;
654 } else
655 value = &duplicated[nextColon-strCapHead];
656
657 for (i=0; i<numOfCorrespondRelations; i++) {
8
Loop condition is true. Entering loop body
658 if (!strcasecmp(correspondRelations[i].capVariable,
9
Taking true branch
659 duplicated)) {
660 if (SPropRecValList_add_record(pThisList,
10
Taking true branch
661 correspondRelations[i]
662 .recordName,
663 value))
664 break;
11
Execution continues on line 668
665 goto next;
666 }
667 }
668 fprintf(stderr__stderrp, "truetype font : Illegal Font Cap.\n");
12
Potential leak of memory pointed to by 'duplicated'
669 result = True(-1);
670 break;
671 next:
672 ;
673 }
674 free(duplicated);
675 }
676 strCapHead = nextColon+1;
677 }
678
679 /* quit: */
680 abort:
681 return result;
682}
683
684/* end of file */