Bug Summary

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