From 58c6a32a6ca954cbdf2943f4a3f64f1ecc385557 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 21 Mar 2023 22:04:30 -0400 Subject: [PATCH] Applied patch from Donn that converts strcpy() calls in ext2spice to "safer" strncpy() calls to prevent string buffer overflow. Also: Reimplemented the loop in the GDS write routine that counts ports and then outputs them in order. It was possible to hang magic for a long time by giving a port a very, very large index number. The new implementation uses qsort() to sort the ports by index, which is obviously much more efficient for the worst case (and efficient enough for all normal cases). --- VERSION | 2 +- calma/CalmaWrite.c | 89 ++++++++++++++++++++++++++++++++----------- calma/CalmaWriteZ.c | 68 ++++++++++++++++++++++----------- calma/calmaInt.h | 10 +++++ ext2spice/ext2spice.c | 28 +++++++------- 5 files changed, 137 insertions(+), 60 deletions(-) diff --git a/VERSION b/VERSION index 0fcb5ebb..e77e1a74 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.383 +8.3.384 diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c index ee76aed3..fe297041 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -50,6 +50,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c #include "utils/styles.h" #include "textio/textio.h" #include "calma/calmaInt.h" +#include "extract/extractInt.h" /* for LabelList */ #include "utils/main.h" /* for Path and CellLibPath */ #include "utils/stack.h" @@ -117,7 +118,7 @@ typedef struct { #define GDS_UNPROCESSED CLIENTDEFAULT #define GDS_PROCESSED 1 -#define PUSHTILE(tp) \ +#define PUSHTILEC(tp) \ if ((tp)->ti_client == (ClientData) GDS_UNPROCESSED) { \ (tp)->ti_client = (ClientData) GDS_PENDING; \ STACKPUSH((ClientData) (tp), SegStack); \ @@ -1244,6 +1245,30 @@ calmaProcessDef(def, outf, do_library) return 0; } +/* + * ---------------------------------------------------------------------------- + * + * compport --- + * + * Compare two port labels by port index. Sorting function used with + * qsort(). + * + * ---------------------------------------------------------------------------- + */ + +int +compport(const void *one, const void *two) +{ + PortLabel *pl1 = (PortLabel *)one; + PortLabel *pl2 = (PortLabel *)two; + + if (pl1->pl_port < pl2->pl_port) + return -1; + if (pl1->pl_port > pl2->pl_port) + return 1; + else + return 0; +} /* * ---------------------------------------------------------------------------- @@ -1383,7 +1408,8 @@ calmaOutFunc(def, f, cliprect) if (CalmaDoLabels) { - int i, ltype, maxport = -1; + int i, ltype, numports = 0; + LabelList *ll = NULL, *newll; for (lab = def->cd_labels; lab; lab = lab->lab_next) { @@ -1395,23 +1421,42 @@ calmaOutFunc(def, f, cliprect) } else { - if ((int)lab->lab_port > maxport) - maxport = (int)lab->lab_port; + newll = (LabelList *)mallocMagic(sizeof(LabelList)); + newll->ll_label = lab; + newll->ll_attr = (unsigned int)lab->lab_port; + newll->ll_next = ll; + ll = newll; + numports++; } } - if (maxport >= 0) - for (i = 0; i <= maxport; i++) - for (lab = def->cd_labels; lab; lab = lab->lab_next) - { - ltype = CIFCurStyle->cs_portText[lab->lab_type]; - type = CIFCurStyle->cs_portLayer[lab->lab_type]; - if ((type >= 0) && ((lab->lab_flags & PORT_DIR_MASK) != 0) && - (lab->lab_port == i)) - { - calmaWriteLabelFunc(lab, ltype, type, f); - /* break; */ /* Do not limit to unique labels! */ - } - } + if (newll != NULL) + { + /* Turn linked list into an array, then run qsort on it */ + /* to sort by port number. */ + + PortLabel *pllist = (PortLabel *)mallocMagic(numports * sizeof(PortLabel)); + i = 0; + while (ll != NULL) + { + pllist[i].pl_label = ll->ll_label; + pllist[i].pl_port = (unsigned int)ll->ll_attr; + freeMagic(ll); + ll = ll->ll_next; + i++; + } + + qsort(pllist, numports, sizeof(PortLabel), compport); + + for (i = 0; i < numports; i++) + { + lab = pllist[i].pl_label; + ltype = CIFCurStyle->cs_portText[lab->lab_type]; + type = CIFCurStyle->cs_portLayer[lab->lab_type]; + if (type >= 0) + calmaWriteLabelFunc(lab, ltype, type, f); + } + freeMagic(pllist); + } } /* End of structure */ @@ -2461,7 +2506,7 @@ calmaMergePaintFunc(tile, cos) if (SegStack == (Stack *)NULL) SegStack = StackNew(64); - PUSHTILE(tile); + PUSHTILEC(tile); while (!StackEmpty(SegStack)) { t = (Tile *) STACKPOP(SegStack); @@ -2629,7 +2674,7 @@ calmaMergePaintFunc(tile, cos) intedges += calmaAddSegment(&lb, is_ext, MIN(RIGHT(t), RIGHT(tp)), TOP(t), MAX(LEFT(t), LEFT(tp)), TOP(t)); - if (!is_ext) PUSHTILE(tp); + if (!is_ext) PUSHTILEC(tp); } if (split_type == 0x3) @@ -2649,7 +2694,7 @@ left_search: intedges += calmaAddSegment(&lb, is_ext, LEFT(t), MIN(TOP(t), TOP(tp)), LEFT(t), MAX(BOTTOM(t), BOTTOM(tp))); - if (!is_ext) PUSHTILE(tp); + if (!is_ext) PUSHTILEC(tp); } if (split_type == 0x0) @@ -2669,7 +2714,7 @@ bottom_search: intedges += calmaAddSegment(&lb, is_ext, MAX(LEFT(t), LEFT(tp)), BOTTOM(t), MIN(RIGHT(t), RIGHT(tp)), BOTTOM(t)); - if (!is_ext) PUSHTILE(tp); + if (!is_ext) PUSHTILEC(tp); } if (split_type == 0x1) @@ -2688,7 +2733,7 @@ right_search: intedges += calmaAddSegment(&lb, is_ext, RIGHT(t), MAX(BOTTOM(t), BOTTOM(tp)), RIGHT(t), MIN(TOP(t), TOP(tp))); - if (!is_ext) PUSHTILE(tp); + if (!is_ext) PUSHTILEC(tp); } /* If tile is isolated, process it now and we're done */ diff --git a/calma/CalmaWriteZ.c b/calma/CalmaWriteZ.c index 200290af..650ad1db 100644 --- a/calma/CalmaWriteZ.c +++ b/calma/CalmaWriteZ.c @@ -60,6 +60,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c #include "utils/styles.h" #include "textio/textio.h" #include "calma/calmaInt.h" +#include "extract/extractInt.h" /* for LabelList */ #include "utils/main.h" /* for Path and CellLibPath */ #include "utils/stack.h" @@ -122,7 +123,7 @@ typedef struct { #define GDS_UNPROCESSED CLIENTDEFAULT #define GDS_PROCESSED 1 -#define PUSHTILE(tp) \ +#define PUSHTILEZ(tp) \ if ((tp)->ti_client == (ClientData) GDS_UNPROCESSED) { \ (tp)->ti_client = (ClientData) GDS_PENDING; \ STACKPUSH((ClientData) (tp), SegStack); \ @@ -1186,6 +1187,7 @@ calmaOutFuncZ(def, f, cliprect) calmaOutputStructZ cos; bool propfound; char *propvalue; + extern int compport(); /* Forward declaration */ cos.f = f; cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect; @@ -1290,7 +1292,8 @@ calmaOutFuncZ(def, f, cliprect) if (CalmaDoLabels) { - int i, ltype, maxport = -1; + int i, ltype, numports = 0; + LabelList *ll = NULL, *newll; for (lab = def->cd_labels; lab; lab = lab->lab_next) { @@ -1302,23 +1305,42 @@ calmaOutFuncZ(def, f, cliprect) } else { - if ((int)lab->lab_port > maxport) - maxport = (int)lab->lab_port; + newll = (LabelList *)mallocMagic(sizeof(LabelList)); + newll->ll_label = lab; + newll->ll_attr = (unsigned int)lab->lab_port; + newll->ll_next = ll; + ll = newll; + numports++; } } - if (maxport >= 0) - for (i = 0; i <= maxport; i++) - for (lab = def->cd_labels; lab; lab = lab->lab_next) - { - ltype = CIFCurStyle->cs_portText[lab->lab_type]; - type = CIFCurStyle->cs_portLayer[lab->lab_type]; - if ((type >= 0) && ((lab->lab_flags & PORT_DIR_MASK) != 0) && - (lab->lab_port == i)) - { - calmaWriteLabelFuncZ(lab, ltype, type, f); - /* break; */ /* Do not limit to unique labels! */ - } - } + if (newll != NULL) + { + /* Turn linked list into an array, then run qsort on it */ + /* to sort by port number. */ + + PortLabel *pllist = (PortLabel *)mallocMagic(numports * sizeof(PortLabel)); + i = 0; + while (ll != NULL) + { + pllist[i].pl_label = ll->ll_label; + pllist[i].pl_port = (unsigned int)ll->ll_attr; + freeMagic(ll); + ll = ll->ll_next; + i++; + } + + qsort(pllist, numports, sizeof(PortLabel), compport); + + for (i = 0; i < numports; i++) + { + lab = pllist[i].pl_label; + ltype = CIFCurStyle->cs_portText[lab->lab_type]; + type = CIFCurStyle->cs_portLayer[lab->lab_type]; + if (type >= 0) + calmaWriteLabelFuncZ(lab, ltype, type, f); + } + freeMagic(pllist); + } } /* End of structure */ @@ -1737,7 +1759,7 @@ calmaWriteContactsZ(f) /* Get clip bounds, so that residue surround is */ /* minimum. Note that these values are in CIF/GDS */ /* units, and the clipping rectangle passed to */ - /* calmaOutFunc is also in CIF/GDS units. */ + /* calmaOutFuncZ is also in CIF/GDS units. */ halfsize = CIFGetContactSize(type, NULL, NULL, NULL) >> 1; @@ -1882,7 +1904,7 @@ calmaMergePaintFuncZ(tile, cos) if (SegStack == (Stack *)NULL) SegStack = StackNew(64); - PUSHTILE(tile); + PUSHTILEZ(tile); while (!StackEmpty(SegStack)) { t = (Tile *) STACKPOP(SegStack); @@ -2050,7 +2072,7 @@ calmaMergePaintFuncZ(tile, cos) intedges += calmaAddSegment(&lb, is_ext, MIN(RIGHT(t), RIGHT(tp)), TOP(t), MAX(LEFT(t), LEFT(tp)), TOP(t)); - if (!is_ext) PUSHTILE(tp); + if (!is_ext) PUSHTILEZ(tp); } if (split_type == 0x3) @@ -2070,7 +2092,7 @@ left_search: intedges += calmaAddSegment(&lb, is_ext, LEFT(t), MIN(TOP(t), TOP(tp)), LEFT(t), MAX(BOTTOM(t), BOTTOM(tp))); - if (!is_ext) PUSHTILE(tp); + if (!is_ext) PUSHTILEZ(tp); } if (split_type == 0x0) @@ -2090,7 +2112,7 @@ bottom_search: intedges += calmaAddSegment(&lb, is_ext, MAX(LEFT(t), LEFT(tp)), BOTTOM(t), MIN(RIGHT(t), RIGHT(tp)), BOTTOM(t)); - if (!is_ext) PUSHTILE(tp); + if (!is_ext) PUSHTILEZ(tp); } if (split_type == 0x1) @@ -2109,7 +2131,7 @@ right_search: intedges += calmaAddSegment(&lb, is_ext, RIGHT(t), MAX(BOTTOM(t), BOTTOM(tp)), RIGHT(t), MIN(TOP(t), TOP(tp))); - if (!is_ext) PUSHTILE(tp); + if (!is_ext) PUSHTILEZ(tp); } /* If tile is isolated, process it now and we're done */ diff --git a/calma/calmaInt.h b/calma/calmaInt.h index 60485aa9..4fb56a2f 100644 --- a/calma/calmaInt.h +++ b/calma/calmaInt.h @@ -216,6 +216,14 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt; UNREADRH(nb, rt); \ } +/* Structure used for sorting ports by number */ + +typedef struct portlabel +{ + Label *pl_label; + unsigned int pl_port; +} PortLabel; + /* Other commonly used globals */ extern HashTable calmaLayerHash; extern int calmaElementIgnore[]; @@ -230,6 +238,8 @@ extern bool calmaIsContactCell; extern char *calmaRecordName(); extern void calmaSkipSet(); +extern int compport(); + /* ------------------- Imports from CIF reading ----------------------- */ extern CellDef *cifReadCellDef; diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 802c4209..aa6c9588 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -3189,8 +3189,8 @@ int spcnAP(dterm, node, resClass, scale, asterm, psterm, m, outf, w) return 1; } - if (asterm) sprintf(afmt, " %s=", asterm); - if (psterm) sprintf(pfmt, " %s=", psterm); + if (asterm) snprintf(afmt, sizeof afmt, " %s=", asterm); + if (psterm) snprintf(pfmt, sizeof pfmt, " %s=", psterm); if (!esDistrJunct || w == -1) goto newFmt; @@ -3206,13 +3206,13 @@ int spcnAP(dterm, node, resClass, scale, asterm, psterm, m, outf, w) { if (asterm) { - fprintf(outf, afmt); + fputs(afmt, outf); esSIvalue(outf, 1.0E-12 * node->efnode_pa[resClass].pa_area * scale * scale * dsc); } if (psterm) { - fprintf(outf, pfmt); + fputs(pfmt, outf); esSIvalue(outf, 1.0E-6 * node->efnode_pa[resClass].pa_perim * scale * dsc); } } @@ -3220,13 +3220,13 @@ int spcnAP(dterm, node, resClass, scale, asterm, psterm, m, outf, w) { if (asterm) { - fprintf(outf, afmt); + fputs(afmt, outf); esSIvalue(outf, 1.0E-12 * ((float)node->efnode_pa[resClass].pa_area * scale * scale) * esScale * esScale * dsc); } if (psterm) { - fprintf(outf, pfmt); + fputs(pfmt, outf); esSIvalue(outf, 1.0E-6 * ((float)node->efnode_pa[resClass].pa_perim * scale) * esScale * dsc); } @@ -3274,12 +3274,12 @@ newFmt: { if (asterm) { - fprintf(outf, afmt); + fputs(afmt, outf); esSIvalue(outf, 1.0E-12 * area * scale * scale / m); } if (psterm) { - fprintf(outf, pfmt); + fputs(pfmt, outf); esSIvalue(outf, 1.0E-6 * perim * scale / m); } } @@ -3287,12 +3287,12 @@ newFmt: { if (asterm) { - fprintf(outf, afmt); + fputs(afmt, outf); esSIvalue(outf, 1.0E-12 * ((float)area * scale * scale) * esScale * esScale); } if (psterm) { - fprintf(outf, pfmt); + fputs(pfmt, outf); esSIvalue(outf, 1.0E-6 * ((float)perim * scale) * esScale); } } @@ -3357,16 +3357,16 @@ int spcnAPHier(dterm, hierName, resClass, scale, asterm, psterm, m, outf) if (esScale < 0) { - fprintf(outf, afmt); + fputs(afmt, outf); esSIvalue(outf, 1.0E-12 * area * scale * scale / m); - fprintf(outf, pfmt); + fputs(pfmt, outf); esSIvalue(outf, 1.0E-6 * perim * scale / m); } else { - fprintf(outf, afmt); + fputs(afmt, outf); esSIvalue(outf, 1.0E-12 * ((float)area * scale) * esScale * esScale); - fprintf(outf, pfmt); + fputs(pfmt, outf); esSIvalue(outf, 1.0E-6 * ((float)perim * scale) * esScale); } return 0;