From f3404f67b725e204616986c0eba9f311cc000674 Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Tue, 24 Feb 2026 20:56:27 -0500 Subject: [PATCH] Came across a weird error today in which some tool inserted bogus data into an array reference in GDS; This may be ignored by most tools (which are not trying to keep track of grid scaling) which read the bogus value which then gets discarded because it is unused (X pitch is irrelevant when there is only one column, and Y pitch is irrelevant when there is only one row). But since magic will try to interpret all input relative to the grid, a bogus value can cause serious problems, and magic needs to actively ignore the appropriate input in the case of rows = 1 or columns = 1. --- calma/CalmaRdcl.c | 29 ++++++++++++++++++++++++++++- calma/CalmaRdpt.c | 28 +++++++++++++++++++++++++++- calma/calma.h | 2 ++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index b036bd26..15cc4531 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -994,12 +994,39 @@ calmaElementSref( * and place the cell in the magic database. However, if this is * a cell to be flattened a la "gds flatten", then we keep the GDS * coordinates, and don't scale to the magic database. + * + * NOTE: Scaling everything in the middle or reading array data + * and then retroactively adjusting the array data read earlier + * is problematic, and probably incorrect. */ for (n = 0; n < nref; n++) { savescale = cifCurReadStyle->crs_scaleFactor; - calmaReadPoint(&refarray[n], 1); + + /* If there is only one column, then X data in the 2nd or 3rd + * entry is irrelevant. If there is only one row, then Y data + * in the 2nd or 3rd entry is irrelevant. Prevent issues caused + * by incorrect/uninitialized data in these positions by ignoring + * them as needed. + */ + if ((n > 0) && (rows == 1)) + { + calmaReadX(&refarray[n], 1); + calmaSkipBytes(4); + refarray[n].p_y = 0; + } + else if ((n > 0) && (cols == 1)) + { + calmaSkipBytes(4); + calmaReadY(&refarray[n], 1); + refarray[n].p_x = 0; + } + else + { + calmaReadPoint(&refarray[n], 1); + } + refunscaled[n] = refarray[n]; // Save for CDFLATGDS cells refarray[n].p_x = CIFScaleCoord(refarray[n].p_x, COORD_EXACT); if (savescale != cifCurReadStyle->crs_scaleFactor) diff --git a/calma/CalmaRdpt.c b/calma/CalmaRdpt.c index ef0cf396..767b2a90 100644 --- a/calma/CalmaRdpt.c +++ b/calma/CalmaRdpt.c @@ -114,6 +114,8 @@ calmaInputRescale( /* * ---------------------------------------------------------------------------- * + * calmaReadX --- + * calmaReadY --- * calmaReadPoint --- * * Read a point from the input. @@ -132,11 +134,17 @@ calmaInputRescale( * encountered, then everything in the GDS planes is rescaled * to match. * + * Notes: + * This routine has been split into individual X and Y reads so that + * array data can be read while ignoring offset information when there + * is only one row or column; otherwise, bad or uninitialized data + * in the record can cause unnecessary and incorrect scaling. + * * ---------------------------------------------------------------------------- */ void -calmaReadPoint( +calmaReadX( Point *p, int iscale) { @@ -163,6 +171,15 @@ calmaReadPoint( } } p->p_x /= calmaReadScale2; +} + + +void +calmaReadY( + Point *p, + int iscale) +{ + int rescale; READI4((p)->p_y); p->p_y *= (calmaReadScale1 * iscale); @@ -188,6 +205,15 @@ calmaReadPoint( p->p_y /= calmaReadScale2; } +void +calmaReadPoint( + Point *p, + int iscale) +{ + calmaReadX(p, iscale); + calmaReadY(p, iscale); +} + /* * ---------------------------------------------------------------------------- diff --git a/calma/calma.h b/calma/calma.h index f745e1d6..394323a9 100644 --- a/calma/calma.h +++ b/calma/calma.h @@ -82,6 +82,8 @@ extern int calmaProcessDefZ(CellDef *def, gzFile outf, bool do_library); #endif extern bool calmaReadI2Record(int type, int *pvalue); extern bool calmaReadI4Record(int type, int *pvalue); +extern void calmaReadX(Point *p, int iscale); +extern void calmaReadY(Point *p, int iscale); extern void calmaReadPoint(Point *p, int iscale); extern bool calmaReadR8(double *pd); extern bool calmaReadStampRecord(int type, int *stampptr);