commit d36df5f1d97b45cc917be188676016a700f8e7ce Author: CentOS Sources Date: Tue May 17 06:47:41 2022 -0400 import transfig-3.2.7b-10.el9 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d6d000a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/fig2dev-3.2.7b.tar.xz diff --git a/.transfig.metadata b/.transfig.metadata new file mode 100644 index 0000000..d13553b --- /dev/null +++ b/.transfig.metadata @@ -0,0 +1 @@ +8097c178b7fff1023112250938cc87837c0f564e SOURCES/fig2dev-3.2.7b.tar.xz diff --git a/SOURCES/0001-Embed-png-and-jpeg-images-unchanged-into-pdfs.patch b/SOURCES/0001-Embed-png-and-jpeg-images-unchanged-into-pdfs.patch new file mode 100644 index 0000000..e02fb40 --- /dev/null +++ b/SOURCES/0001-Embed-png-and-jpeg-images-unchanged-into-pdfs.patch @@ -0,0 +1,77 @@ +From 841c88cdd31eece97a929fbc01902a33d6168b00 Mon Sep 17 00:00:00 2001 +From: Thomas Loimer +Date: Sun, 10 Nov 2019 22:53:23 +0100 +Subject: [PATCH 1/8] Embed png and jpeg images unchanged into pdfs + +Before, with the "-dAutoFilterColorImages=false -dColorImageFilter=/DCTEncode" +switches to pdf, png-files were re-encoded to jpegs. +--- + CHANGES | 9 ++++++++- + fig2dev/dev/genpdf.c | 6 ++---- + version.m4 | 6 +++--- + 3 files changed, 13 insertions(+), 8 deletions(-) + +diff --git a/CHANGES b/CHANGES +index 2a9c1fb..2cdfda0 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -2,7 +2,14 @@ Changes to fig2dev + =============================================================================== + Version 3.2 + =============================================================================== +-Patchlevel 7b (Oct 2019) ++Patchlevel Xx (Xxx 20xx) ++ ++BUGS FIXED: ++ o Embed images in pdfs with their original compression type, i.e., leave ++ the gs switch "-dAutoFilterColorImages" at its default value "true". ++ ++------------------------------------- ++Patchlevel 7b (Nov 2019) + + NEW FEATURES: + o A X color database is not needed, but can be provided. The location of +diff --git a/fig2dev/dev/genpdf.c b/fig2dev/dev/genpdf.c +index d5b3a5a..1ddaa40 100644 +--- a/fig2dev/dev/genpdf.c ++++ b/fig2dev/dev/genpdf.c +@@ -91,10 +91,8 @@ genpdf_start(F_compound *objects) + */ + /* -o ... is equivalent to -dBATCH -dNOPAUSE, see ghostscript Use.htm + and -dBATCH is equivalent to -c quit */ +- sprintf(com, "%s -q -sAutoRotatePages=None " +- "-dAutoFilterColorImages=false -dColorImageFilter=/DCTEncode " +- "-sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -o '%s' -", +- GSEXE, ofile); ++ sprintf(com, "%s -q -sAutoRotatePages=None -sDEVICE=pdfwrite " ++ "-dPDFSETTINGS=/prepress -o '%s' -", GSEXE, ofile); + (void) signal(SIGPIPE, pdf_broken_pipe); + if ((tfp = popen(com, "w")) == 0) { + fprintf(stderr, "fig2dev: Cannot open pipe to ghostscript\n"); +diff --git a/version.m4 b/version.m4 +index faf88ad..fa546d9 100644 +--- a/version.m4 ++++ b/version.m4 +@@ -2,7 +2,7 @@ dnl Fig2dev: Translate Fig code to various Devices + dnl Copyright (c) 1991 by Micah Beck + dnl Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + dnl Parts Copyright (c) 1989-2015 by Brian V. Smith +-dnl Parts Copyright (c) 2015-2018 by Thomas Loimer ++dnl Parts Copyright (c) 2015-2019 by Thomas Loimer + dnl + dnl Any party obtaining a copy of these files is granted, free of charge, a + dnl full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -22,8 +22,8 @@ dnl Thus, configure.ac can remain unchanged between different versions. + dnl The values in this file are set by update_version_m4 if + dnl ./configure is called with --enable_versioning. + +-m4_define([FIG_VERSION], [3.2.7b]) ++m4_define([FIG_VERSION], [3.2.7b-dev]) + + dnl AC_INIT does not have access to shell variables. + dnl Therefore, define RELEASEDATE as a macro. +-m4_define([RELEASEDATE], [Oct 2019]) ++m4_define([RELEASEDATE], [Nov 2019]) +-- +2.24.1 + diff --git a/SOURCES/0002-Allow-fig-2-text-ending-with-multiple-A-ticket-55.patch b/SOURCES/0002-Allow-fig-2-text-ending-with-multiple-A-ticket-55.patch new file mode 100644 index 0000000..2d0ba87 --- /dev/null +++ b/SOURCES/0002-Allow-fig-2-text-ending-with-multiple-A-ticket-55.patch @@ -0,0 +1,71 @@ +From 19db5fe6f77ebad91af4b4ef0defd61bd0bb358f Mon Sep 17 00:00:00 2001 +From: Thomas Loimer +Date: Wed, 4 Dec 2019 17:56:04 +0100 +Subject: [PATCH 2/8] Allow fig 2 text ending with multiple ^A, ticket #55 + +--- + CHANGES | 2 ++ + fig2dev/read.c | 4 ++-- + fig2dev/tests/read.at | 11 +++++++++++ + 3 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/CHANGES b/CHANGES +index 2cdfda0..edd0843 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -5,6 +5,8 @@ Version 3.2 + Patchlevel Xx (Xxx 20xx) + + BUGS FIXED: ++ Ticket numbers refer to https://sourceforge.net/p/mcj/tickets/#. ++ o Allow Fig v2 text strings ending with multiple ^A. Ticket #55. + o Embed images in pdfs with their original compression type, i.e., leave + the gs switch "-dAutoFilterColorImages" at its default value "true". + +diff --git a/fig2dev/read.c b/fig2dev/read.c +index af84531..09bd17d 100644 +--- a/fig2dev/read.c ++++ b/fig2dev/read.c +@@ -3,7 +3,7 @@ + * Copyright (c) 1991 by Micah Beck + * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + * Parts Copyright (c) 1989-2015 by Brian V. Smith +- * Parts Copyright (c) 2015-2018 by Thomas Loimer ++ * Parts Copyright (c) 2015-2019 by Thomas Loimer + * + * Any party obtaining a copy of these files is granted, free of charge, a + * full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -1328,7 +1328,7 @@ read_textobject(FILE *fp) + If we do not find the CONTROL-A on this line then this must + be a multi-line text object and we will have to read more. */ + +- n = sscanf(buf,"%*d%d%d%lf%d%d%d%lf%d%lf%lf%d%d%[^\1]%[\1]", ++ n = sscanf(buf,"%*d%d%d%lf%d%d%d%lf%d%lf%lf%d%d%[^\1]%1[\1]", + &t->type, &t->font, &t->size, &t->pen, + &t->color, &t->depth, &t->angle, + &t->flags, &t->height, &t->length, +diff --git a/fig2dev/tests/read.at b/fig2dev/tests/read.at +index a606de0..c36d07a 100644 +--- a/fig2dev/tests/read.at ++++ b/fig2dev/tests/read.at +@@ -359,6 +359,17 @@ EOF + ], 0, ignore) + AT_CLEANUP + ++AT_SETUP([allow text ending with multiple ^A, ticket #55]) ++AT_KEYWORDS([read.c]) ++AT_CHECK([fig2dev -L box < +Date: Tue, 10 Dec 2019 13:17:36 +0100 +Subject: [PATCH 3/8] Reject huge arrow types, ticket #57 + +An arrow type being large enough would pass the test for +a valid type by integer overflow. +--- + CHANGES | 1 + + fig2dev/arrow.c | 13 ++++++++----- + fig2dev/tests/read.at | 12 ++++++++++++ + 3 files changed, 21 insertions(+), 5 deletions(-) + +diff --git a/CHANGES b/CHANGES +index edd0843..964dc84 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -6,6 +6,7 @@ Patchlevel Xx (Xxx 20xx) + + BUGS FIXED: + Ticket numbers refer to https://sourceforge.net/p/mcj/tickets/#. ++ o Reject huge arrow types causing integer overflow. Ticket #57. + o Allow Fig v2 text strings ending with multiple ^A. Ticket #55. + o Embed images in pdfs with their original compression type, i.e., leave + the gs switch "-dAutoFilterColorImages" at its default value "true". +diff --git a/fig2dev/arrow.c b/fig2dev/arrow.c +index a8e7fd0..34bcf18 100644 +--- a/fig2dev/arrow.c ++++ b/fig2dev/arrow.c +@@ -1,9 +1,10 @@ + /* + * Fig2dev: Translate Fig code to various Devices +- * Copyright (c) 1985 by Supoj Sutantavibul + * Copyright (c) 1991 by Micah Beck +- * Parts Copyright (c) 1989-2002 by Brian V. Smith +- * Parts Copyright (c) 2015-2018 by Thomas Loimer ++ * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul ++ * Parts Copyright (c) 1989-2015 by Brian V. Smith ++ * Parts Copyright (c) 2015-2019 by Thomas Loimer ++ * + * + * Any party obtaining a copy of these files is granted, free of charge, a + * full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -78,7 +79,9 @@ make_arrow(int type, int style, double thickness, double wid, double ht) + { + F_arrow *a; + +- if (style < 0 || style > 1 || type < 0 || (type + 1) * 2 > NUMARROWS) ++ if (style < 0 || style > 1 || type < 0 || ++ /* beware of int overflow */ ++ type > NUMARROWS || (type + 1) * 2 > NUMARROWS) + return NULL; + if (NULL == (Arrow_malloc(a))) { + put_msg(Err_mem); +@@ -90,7 +93,7 @@ make_arrow(int type, int style, double thickness, double wid, double ht) + + a->type = type; + a->style = style; +- a->thickness = thickness*THICK_SCALE; ++ a->thickness = thickness * THICK_SCALE; + a->wid = wid; + a->ht = ht; + return a; +diff --git a/fig2dev/tests/read.at b/fig2dev/tests/read.at +index c36d07a..e9a71a3 100644 +--- a/fig2dev/tests/read.at ++++ b/fig2dev/tests/read.at +@@ -135,6 +135,18 @@ A single point with a backward arrow - remove the arrow. + ]) + AT_CLEANUP + ++AT_SETUP([reject huge arrow-type, ticket #57]) ++AT_KEYWORDS(arrow.c arrow) ++AT_CHECK([fig2dev -L box < +Date: Wed, 11 Dec 2019 21:36:46 +0100 +Subject: [PATCH 4/8] Convert polygons with too few points to polylines + +As a side effect, this also fixes ticket #56. +--- + CHANGES | 1 + + fig2dev/read.c | 16 ++++++++++++++++ + fig2dev/tests/read.at | 11 +++++++++++ + 3 files changed, 28 insertions(+) + +diff --git a/CHANGES b/CHANGES +index 964dc84..b2f7006 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -6,6 +6,7 @@ Patchlevel Xx (Xxx 20xx) + + BUGS FIXED: + Ticket numbers refer to https://sourceforge.net/p/mcj/tickets/#. ++ o Convert polygons having too few points to polylines. Ticket #56. + o Reject huge arrow types causing integer overflow. Ticket #57. + o Allow Fig v2 text strings ending with multiple ^A. Ticket #55. + o Embed images in pdfs with their original compression type, i.e., leave +diff --git a/fig2dev/read.c b/fig2dev/read.c +index 09bd17d..9500091 100644 +--- a/fig2dev/read.c ++++ b/fig2dev/read.c +@@ -793,8 +793,10 @@ read_ellipseobject(void) + /* + * Sanitize line objects. Return 0 on success, -1 otherwise. + * On error, call free_linestorage(l) after sanitize_lineobject(). ++ * + * polylines: remove fill, if less than 3 points + * remove arrows, if only one point ++ * polygons: convert to polyline if less than 3 unique points + * rectangles, polygons: last point must coincide with first point + * rectangle: convert to polygon, if not 5 points + * rectangle with rounded corners: error, if not 5 points +@@ -854,6 +856,20 @@ sanitize_lineobject( + q->y = l->points->y; + } + ++ if (l->type == T_POLYGON) { ++ int npts; ++ ++ q = l->points; ++ for (npts = 1; q->next && npts < 4; q = q->next) ++ ++npts; ++ if (npts < 4 ) { ++ put_msg("A polygon with %d points at line %d - convert to a polyline.", ++ npts, line_no); ++ l->type = T_POLYLINE; ++ return 0; ++ } ++ } ++ + if (l->type == T_BOX || l->type == T_ARC_BOX || l->type == T_PIC_BOX) { + int npts = 1; + for (q = l->points; q->next; q = q->next) +diff --git a/fig2dev/tests/read.at b/fig2dev/tests/read.at +index e9a71a3..4ef8747 100644 +--- a/fig2dev/tests/read.at ++++ b/fig2dev/tests/read.at +@@ -147,6 +147,17 @@ EOF + ]) + AT_CLEANUP + ++AT_SETUP([convert short polygon to polyline, ticket #56]) ++AT_KEYWORDS(read.c polygon) ++AT_CHECK([fig2dev -L ptk < +Date: Sat, 14 Dec 2019 23:10:04 +0100 +Subject: [PATCH 5/8] Correctly scan embedded pdfs for /MediaBox value + +This applies two patches from the opensuse source rpm, +https://download.opensuse.org/repositories/openSUSE:/Factory/standard/src/xfig-3.2.7b-1.1.src.rpm +transfig.3.2.5-binderman.dif and transfig.3.2.5d-mediaboxrealnb.dif. +--- + CHANGES | 1 + + fig2dev/dev/readeps.c | 31 ++++++++------ + fig2dev/tests/Makefile.am | 15 ++++--- + fig2dev/tests/bitmaps.at | 5 +++ + fig2dev/tests/data/cross.pdf | 62 +++++++++++++++++++++++++++ + fig2dev/tests/test2.c | 82 ++++++++++++++++++++++++++++++++++++ + transfig/sys.c | 3 ++ + 7 files changed, 182 insertions(+), 17 deletions(-) + create mode 100644 fig2dev/tests/data/cross.pdf + create mode 100644 fig2dev/tests/test2.c + +diff --git a/CHANGES b/CHANGES +index b2f7006..4a414fa 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -6,6 +6,7 @@ Patchlevel Xx (Xxx 20xx) + + BUGS FIXED: + Ticket numbers refer to https://sourceforge.net/p/mcj/tickets/#. ++ o Correctly scan embedded pdfs for /MediaBox value. + o Convert polygons having too few points to polylines. Ticket #56. + o Reject huge arrow types causing integer overflow. Ticket #57. + o Allow Fig v2 text strings ending with multiple ^A. Ticket #55. +diff --git a/fig2dev/dev/readeps.c b/fig2dev/dev/readeps.c +index ec25504..502f4bb 100644 +--- a/fig2dev/dev/readeps.c ++++ b/fig2dev/dev/readeps.c +@@ -1,7 +1,9 @@ + /* + * Fig2dev: Translate Fig code to various Devices +- * Parts Copyright (c) 1989-2007 by Brian V. Smith +- * Parts Copyright (c) 2015-2017 by Thomas Loimer ++ * Copyright (c) 1991 by Micah Beck ++ * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul ++ * Parts Copyright (c) 1989-2015 by Brian V. Smith ++ * Parts Copyright (c) 2015-2019 by Thomas Loimer + * + * Any party obtaining a copy of these files is granted, free of charge, a + * full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -83,18 +85,23 @@ read_eps_pdf(FILE *file, int filetype, F_pic *pic, int *llx, int* lly, + while (fgets(buf, BUFSIZ, file) != NULL) { + /* look for /MediaBox for pdf file */ + if (pdf_flag) { +- if (!strncmp(buf, "/MediaBox", 9)) { /* look for the MediaBox spec */ +- c = strchr(buf, '[') + 1; +- if (c && sscanf(c, "%d %d %d %d", llx, lly, &urx, &ury) < 4) +- { +- *llx = *lly = 0; +- urx = paperdef[0].width*72; +- ury = paperdef[0].height*72; +- put_msg("Bad MediaBox in imported PDF file %s, assuming %s size", +- pic->file, metric? "A4" : "Letter" ); ++ for (c = buf; (c = strchr(c,'/')); ++c) { ++ if (!strncmp(c, "/MediaBox", 9)) { ++ c = strchr(c, '['); ++ if (c && sscanf(c + 1, "%d %d %d %d", ++ llx, lly, &urx, &ury) < 4) { ++ *llx = *lly = 0; ++ urx = paperdef[0].width*72; ++ ury = paperdef[0].height*72; ++ put_msg("Bad MediaBox in imported PDF file %s, assuming %s size", ++ pic->file, metric? "A4" : "Letter" ); ++ } ++ pic->bit_size.x = urx - (*llx); ++ pic->bit_size.y = ury - (*lly); ++ break; + } + } +- /* look for bounding box for EPS file */ ++ /* look for bounding box for EPS file */ + } else if (!nested && !strncmp(buf, "%%BoundingBox:", 14)) { + c = buf + 14; + /* skip past white space */ +diff --git a/fig2dev/tests/Makefile.am b/fig2dev/tests/Makefile.am +index 4b83e0b..389f984 100644 +--- a/fig2dev/tests/Makefile.am ++++ b/fig2dev/tests/Makefile.am +@@ -4,7 +4,7 @@ + # Copyright (c) 1991 by Micah Beck + # Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + # Parts Copyright (c) 1989-2015 by Brian V. Smith +-# Parts Copyright (c) 2015-2018 by Thomas Loimer ++# Parts Copyright (c) 2015-2019 by Thomas Loimer + # + # Any party obtaining a copy of these files is granted, free of charge, a + # full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -16,7 +16,7 @@ + # and this permission notice remain intact. + + # fig2dev/tests/Makefile.am +-# Author: Thomas Loimer, 2016-2018. ++# Author: Thomas Loimer, 2016-2019. + + + # testsuite and package.m4 must be distributed, hence they are +@@ -39,8 +39,8 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac + echo 'm4_define([AT_PACKAGE_URL], [@PACKAGE_URL@])'; \ + } >'$(srcdir)/package.m4' + +-check_PROGRAMS = test1 +-# test1 calls malloc(). AC_FUNC_MALLOC may replace malloc() by rpl_malloc() ++check_PROGRAMS = test1 test2 ++# test1 called malloc(). AC_FUNC_MALLOC may replace malloc() by rpl_malloc() + # which is defined in malloc.o. The latter is contained in $(LIBOBJS) in + # ${LIBOBJDIR}. Specifically, ./configure CFLAGS="-fsanitize=address" causes + # this replacment. Unfortunately, using test1_LDADD, causes make distcheck to +@@ -54,9 +54,14 @@ check_PROGRAMS = test1 + + # keep the definitions below in sync with those in ../dev/Makefile.am + if ENABLE_I18N +-AM_CPPFLAGS = -DI18N_DATADIR="\"$(i18ndir)\"" ++test1_CPPFLAGS = -DI18N_DATADIR="\"$(i18ndir)\"" + endif + ++test2_CPPFLAGS = -I$(top_srcdir)/fig2dev ++test2_LDADD = $(top_builddir)/fig2dev/dev/readeps.$(OBJEXT) ++test2_DEPENDENCIES = $(test2_LDADD) ++ ++ + check-local: atconfig $(TESTSUITE) atlocal + $(SHELL) '$(TESTSUITE)' INSTALLCHECK=no $(TESTSUITEFLAGS) + +diff --git a/fig2dev/tests/bitmaps.at b/fig2dev/tests/bitmaps.at +index 91d5b54..1fea0f8 100644 +--- a/fig2dev/tests/bitmaps.at ++++ b/fig2dev/tests/bitmaps.at +@@ -235,3 +235,8 @@ EOF` + # 1433 on ubuntu 16.04.2 with ghostscript 9.18 + AT_CHECK([test $blackpixels -gt 1431 && test $blackpixels -lt 1494]) + AT_CLEANUP ++ ++AT_SETUP([find /MediaBox in pdf file]) ++AT_KEYWORDS(pdf) ++AT_CHECK(["$abs_builddir"/test2 "$srcdir/data/cross.pdf"], 0, ignore) ++AT_CLEANUP +diff --git a/fig2dev/tests/data/cross.pdf b/fig2dev/tests/data/cross.pdf +new file mode 100644 +index 0000000..e1e7e4d +--- /dev/null ++++ b/fig2dev/tests/data/cross.pdf +@@ -0,0 +1,62 @@ ++%PDF-1.4 ++5 0 obj ++<> ++stream ++xM 0 {O'Qxj` ++R ++$'ni=^tB Z)AВ{4LDDؾWާj_.rd?endstream ++endobj ++6 0 obj ++91 ++endobj ++4 0 obj ++<> ++/Contents 5 0 R ++>> ++endobj ++3 0 obj ++<< /Type /Pages /Kids [ ++4 0 R ++] /Count 1 ++>> ++endobj ++1 0 obj ++<> ++endobj ++7 0 obj ++<>endobj ++8 0 obj ++<> ++endobj ++2 0 obj ++<>endobj ++xref ++0 9 ++0000000000 65535 f ++0000000376 00000 n ++0000000514 00000 n ++0000000317 00000 n ++0000000188 00000 n ++0000000009 00000 n ++0000000170 00000 n ++0000000424 00000 n ++0000000485 00000 n ++trailer ++<< /Size 10 /Root 1 0 R /Info 2 0 R ++/ID [] ++>> ++startxref ++670 ++%%EOF +diff --git a/fig2dev/tests/test2.c b/fig2dev/tests/test2.c +new file mode 100644 +index 0000000..04e92d7 +--- /dev/null ++++ b/fig2dev/tests/test2.c +@@ -0,0 +1,82 @@ ++/* ++ * Fig2dev: Translate Fig code to various Devices ++ * Copyright (c) 1991 by Micah Beck ++ * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul ++ * Parts Copyright (c) 1989-2015 by Brian V. Smith ++ * Parts Copyright (c) 2015-2019 by Thomas Loimer ++ * ++ * Any party obtaining a copy of these files is granted, free of charge, a ++ * full and unrestricted irrevocable, world-wide, paid up, royalty-free, ++ * nonexclusive right and license to deal in this software and documentation ++ * files (the "Software"), including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense and/or sell copies ++ * of the Software, and to permit persons who receive copies from any such ++ * party to do so, with the only requirement being that the above copyright ++ * and this permission notice remain intact. ++ * ++ */ ++ ++/* ++ * test2.c: Check, whether read_pdf() finds the bounding box of a pdf file. ++ * Author: Thomas Loimer, 2019-12-14 ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include ++#include ++#include ++ ++#include "bool.h" ++#include "object.h" ++ ++/* the function to be tested, in $(top_srcdir)/fig2dev/dev/readeps.c */ ++extern int read_pdf(FILE *file, int type, F_pic *pic, int *llx, int *lly); ++ ++/* symbols that are needed when calling read_pdf() */ ++int urx = 0; ++int ury = 0; ++int metric = 0; ++FILE *tfp; ++const struct _paperdef /* from fig2dev.h */ ++{ ++ char *name; ++ int width; ++ int height; ++} paperdef[1] = {{"letter", 8, 12}}; ++ ++ ++void put_msg(const char *fmt, const char *file, const char *size) ++{ ++ fprintf(stderr, fmt, file, size); ++} ++ ++int ++main(int argc, char *argv[]) ++{ ++ (void) argc; ++ int llx = -1; ++ int lly = -1; ++ FILE *file; ++ F_pic pic; ++ ++ tfp = stdout; ++ pic.file = argv[1]; ++ ++ file = fopen(argv[1], "rb"); ++ if (file == NULL) { ++ fprintf(stderr, "Test file %s not found.\n", argv[1]); ++ exit(EXIT_FAILURE); ++ } ++ ++ if (read_pdf(file, 0, &pic, &llx, &lly) == 1 && ++ pic.bit_size.x != 10 && pic.bit_size.y != 10) { ++ fprintf(stdout, "read_pdf found: width = %d, height = %d\n", ++ pic.bit_size.x, pic.bit_size.y); ++ exit(EXIT_SUCCESS); ++ } else { ++ exit(EXIT_FAILURE); ++ } ++} +diff --git a/transfig/sys.c b/transfig/sys.c +index c070ee6..30e8d3d 100644 +--- a/transfig/sys.c ++++ b/transfig/sys.c +@@ -2,6 +2,8 @@ + * TransFig: Facility for Translating Fig code + * Copyright (c) 1991 by Micah Beck + * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul ++ * Parts Copyright (c) 1989-2015 by Brian V. Smith ++ * Parts Copyright (c) 2015-2019 by Thomas Loimer + * + * Any party obtaining a copy of these files is granted, free of charge, a + * full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -39,6 +41,7 @@ sysls(void) + i += 1; + c = fgetc(ls); + } ++ pclose(ls); + sysbuf[i] = '\0'; + return sysbuf; + } +-- +2.24.1 + diff --git a/SOURCES/0006-fig2dev-version-prints-version-information.patch b/SOURCES/0006-fig2dev-version-prints-version-information.patch new file mode 100644 index 0000000..edd1953 --- /dev/null +++ b/SOURCES/0006-fig2dev-version-prints-version-information.patch @@ -0,0 +1,30 @@ +From 560e633910a28f81b6607cf81e53026ac96034bf Mon Sep 17 00:00:00 2001 +From: Thomas Loimer +Date: Sun, 15 Dec 2019 21:32:18 +0100 +Subject: [PATCH 6/8] "fig2dev --version" prints version information + +--- + fig2dev/fig2dev.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/fig2dev/fig2dev.c b/fig2dev/fig2dev.c +index 0866a71..479b484 100644 +--- a/fig2dev/fig2dev.c ++++ b/fig2dev/fig2dev.c +@@ -218,6 +218,13 @@ get_args(int argc, char *argv[]) + + if (argc == 1) + fprintf(stderr, Usage, prog, prog); ++ ++ /* print the version, for the comfort of the autotest tests */ ++ if (!strcmp(argv[1], "--version")) { ++ printf("fig2dev Version %s\n", PACKAGE_VERSION); ++ exit(EXIT_SUCCESS); ++ } ++ + /* sum of all arguments */ + while ((c = fig_getopt(argc, argv, ARGSTRING)) != EOF) { + +-- +2.24.1 + diff --git a/SOURCES/0007-Use-getopt-from-standard-libraries-if-available.patch b/SOURCES/0007-Use-getopt-from-standard-libraries-if-available.patch new file mode 100644 index 0000000..ffff990 --- /dev/null +++ b/SOURCES/0007-Use-getopt-from-standard-libraries-if-available.patch @@ -0,0 +1,173 @@ +From 93795dd396730c80e63767dede7777f4cb7dc383 Mon Sep 17 00:00:00 2001 +From: Thomas Loimer +Date: Sun, 15 Dec 2019 21:34:34 +0100 +Subject: [PATCH 7/8] Use getopt() from standard libraries, if available + +--- + configure.ac | 10 +++++----- + fig2dev/Makefile.am | 2 +- + fig2dev/Nmakefile | 6 +++--- + fig2dev/fig2dev.c | 12 +++++++----- + fig2dev/{ => lib}/getopt.c | 12 +++--------- + 5 files changed, 19 insertions(+), 23 deletions(-) + rename fig2dev/{ => lib}/getopt.c (91%) + +diff --git a/configure.ac b/configure.ac +index e88b27a..8e955ee 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -5,7 +5,7 @@ AC_COPYRIGHT([Fig2dev: Translate Fig code to various Devices + Copyright (c) 1991 by Micah Beck + Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + Parts Copyright (c) 1989-2015 by Brian V. Smith +-Parts Copyright (c) 2015-2018 by Thomas Loimer ++Parts Copyright (c) 2015-2019 by Thomas Loimer + + Any party obtaining a copy of these files is granted, free of charge, a + full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -19,7 +19,7 @@ and this permission notice remain intact. + + # + # configure.ac +-# Author: Thomas Loimer, 2015-2018. ++# Author: Thomas Loimer, 2015-2019. + # + + dnl Define m4 variables for use in AC_INIT and AC_DEFINE below. +@@ -366,9 +366,9 @@ AS_IF([test "$tl_cv_func__setmode" = yes], + + # Check for functions and, if not found, use the corresponding + # replacement, e.g., strstr.c, in the top srcdir. Sets, e.g., +-# HAVE_STRSTR. Any modern system should have these functions, so +-# this are obsolete checks. +-AC_REPLACE_FUNCS([isascii strstr strchr strrchr strcasecmp strncasecmp \ ++# HAVE_STRSTR. Except possibly getopt(), any modern system should have these ++# functions, so all except one are obsolete checks. ++AC_REPLACE_FUNCS([getopt isascii strstr strchr strrchr strcasecmp strncasecmp \ + strdup strndup]) + + # Place the replacement functions into this dir. +diff --git a/fig2dev/Makefile.am b/fig2dev/Makefile.am +index d00ac54..70ae569 100644 +--- a/fig2dev/Makefile.am ++++ b/fig2dev/Makefile.am +@@ -39,7 +39,7 @@ bin_PROGRAMS = fig2dev + fig2dev_SOURCES = alloc.h arrow.c bool.h bound.h bound.c colors.h colors.c \ + creationdate.h creationdate.c drivers.h fig2dev.h fig2dev.c free.h free.c \ + iso2tex.c localmath.h localmath.c object.h read1_3.c read.h read.c \ +- trans_spline.h trans_spline.c pi.h getopt.c ++ trans_spline.h trans_spline.c pi.h + + # CONFIG_HEADER is config.h, which contains PACKAGE_VERSION. If that + # changes, fig2dev should take up the new version string. +diff --git a/fig2dev/Nmakefile b/fig2dev/Nmakefile +index 7623e40..bba38c9 100644 +--- a/fig2dev/Nmakefile ++++ b/fig2dev/Nmakefile +@@ -2,7 +2,7 @@ + # Copyright (c) 1991 by Micah Beck + # Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + # Parts Copyright (c) 1989-2015 by Brian V. Smith +-# Parts Copyright (c) 2015-2018 by Thomas Loimer ++# Parts Copyright (c) 2015-2019 by Thomas Loimer + # + # Any party obtaining a copy of these files is granted, free of charge, a + # full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -14,7 +14,7 @@ + # and this permission notice remain intact. + + # fig2dev/Nmakefile +-# Author: Thomas Loimer, 2018. ++# Author: Thomas Loimer, 2018, 2019. + + ############################################################# + # +@@ -84,7 +84,7 @@ CFLAGS = /I. /Idev /nologo /W1 /DWIN32 /D_BIND_TO_CURRENT_VCLIBS_VERSION=1 \ + REPL_LIBS = lib/strndup.c + + FIG2DEV_SRCS = arrow.c bound.c colors.c creationdate.c fig2dev.c free.c \ +- getopt.c iso2tex.c localmath.c read.c read1_3.c trans_spline.c \ ++ iso2tex.c localmath.c read.c read1_3.c trans_spline.c \ + dev/asc85ec.c dev/genbitmaps.c dev/genbox.c dev/gencgm.c dev/gendxf.c \ + dev/genemf.c dev/genepic.c dev/gengbx.c dev/genge.c dev/genibmgl.c \ + dev/genlatex.c dev/genmap.c dev/genmf.c dev/genmp.c dev/genpdf.c \ +diff --git a/fig2dev/fig2dev.c b/fig2dev/fig2dev.c +index 479b484..d8c5e2a 100644 +--- a/fig2dev/fig2dev.c ++++ b/fig2dev/fig2dev.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + /* In Windows, _setmode() is declared in , O_BINARY in . It + * accepts two arguments and sets file mode to text or binary. */ +@@ -44,10 +45,11 @@ + #include "bound.h" + #include "read.h" + +-/* the three lines below could go into a getopt.h file */ +-extern int fig_getopt(int nargc, char **nargv, char *ostr); /* getopt.c */ +-extern char *optarg; /* getopt.c */ +-extern int optind; /* getopt.c */ ++#ifndef HAVE_GETOPT ++extern int getopt(int argc, char *argv[], const char *ostr); ++extern char *optarg; ++extern int optind; ++#endif + + char Err_badarg[] = "Argument -%c unknown to %s driver."; + char Err_mem[] = "Running out of memory."; +@@ -226,7 +228,7 @@ get_args(int argc, char *argv[]) + } + + /* sum of all arguments */ +- while ((c = fig_getopt(argc, argv, ARGSTRING)) != EOF) { ++ while ((c = getopt(argc, argv, ARGSTRING)) != EOF) { + + /* global (all drivers) option handling */ + switch (c) { +diff --git a/fig2dev/getopt.c b/fig2dev/lib/getopt.c +similarity index 91% +rename from fig2dev/getopt.c +rename to fig2dev/lib/getopt.c +index 867a9fe..f3d1845 100644 +--- a/fig2dev/getopt.c ++++ b/fig2dev/lib/getopt.c +@@ -2,8 +2,8 @@ + * Fig2dev: Translate Fig code to various Devices + * Copyright (c) 1991 by Micah Beck + * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul +- * Parts Copyright (c) 1989-2007 by Brian V. Smith +- * Parts Copyright (c) 2015-2017 by Thomas Loimer ++ * Parts Copyright (c) 1989-2015 by Brian V. Smith ++ * Parts Copyright (c) 2015-2019 by Thomas Loimer + * + * Any party obtaining a copy of these files is granted, free of charge, a + * full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -37,12 +37,6 @@ + #include + #include + +-/* +-#ifndef lint +-static char sccsfid[] = "@(#) getopt.c 5.0 (UTZoo) 1985"; +-#endif +-*/ +- + #define ARGCH (int)':' + #define BADCH (int)'?' + #define EMSG "" +@@ -59,7 +53,7 @@ char *optarg; /* argument associated with option */ + fputc(optc,stderr); fputc('\n',stderr); return BADCH + + int +-fig_getopt(int nargc, char **nargv, char *ostr) ++getopt(int nargc, char **nargv, const char *ostr) + { + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ +-- +2.24.1 + diff --git a/SOURCES/0008-Replace-most-calls-to-fgets-by-getline-in-read.c.patch b/SOURCES/0008-Replace-most-calls-to-fgets-by-getline-in-read.c.patch new file mode 100644 index 0000000..4a1a914 --- /dev/null +++ b/SOURCES/0008-Replace-most-calls-to-fgets-by-getline-in-read.c.patch @@ -0,0 +1,1857 @@ +From 41b9bb838a3d544539f6e68aa4f87d70ef7d45ce Mon Sep 17 00:00:00 2001 +From: Thomas Loimer +Date: Sun, 5 Jan 2020 19:22:12 +0100 +Subject: [PATCH 8/8] Replace most calls to fgets() by getline() in read.c + +Also, fig files version 1.4 must begin with `#FIG 1.4`. Previously, a `#` in the +first line was sufficient to detect at least a version 1.4 fig file. +Move some variables with file scope into functions. + +This commit fixes tickets #58, #59, #61, #62, #67, #78 and #79. + +In fig2dev/lib/, replacements are provided for some library functions used in +fig2dev, e.g., strncasecmp(), strrchr(), etc. The getline() function was +introduced more recently than any of the functions provided in fig2dev/lib. +Nevertheless, for getline() a replacement function is not provided. It seems, +that all the replacement functions do not work, but nobody noticed. Therefore, +only provide a replacement function for getline() if that turns out to +be useful. +The replacement functions do not work, because a header file providing the +necessary function declarations is missing. +--- + configure.ac | 3 +- + fig2dev/fig2dev.c | 4 +- + fig2dev/fig2dev.h | 4 +- + fig2dev/read.c | 904 +++++++++++++++++++++++------------------- + fig2dev/read1_3.c | 12 +- + fig2dev/tests/read.at | 29 +- + 6 files changed, 533 insertions(+), 423 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 8e955ee..881a39d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -5,7 +5,7 @@ AC_COPYRIGHT([Fig2dev: Translate Fig code to various Devices + Copyright (c) 1991 by Micah Beck + Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + Parts Copyright (c) 1989-2015 by Brian V. Smith +-Parts Copyright (c) 2015-2019 by Thomas Loimer ++Parts Copyright (c) 2015-2020 by Thomas Loimer + + Any party obtaining a copy of these files is granted, free of charge, a + full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -327,6 +327,7 @@ dnl Just provide our own pi + # example. + AC_HEADER_STDBOOL + AC_TYPE_SIZE_T ++AC_TYPE_SSIZE_T + + # + # Checks for library functions. +diff --git a/fig2dev/fig2dev.c b/fig2dev/fig2dev.c +index d8c5e2a..62ec099 100644 +--- a/fig2dev/fig2dev.c ++++ b/fig2dev/fig2dev.c +@@ -3,7 +3,7 @@ + * Copyright (c) 1991 by Micah Beck + * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + * Parts Copyright (c) 1989-2015 by Brian V. Smith +- * Parts Copyright (c) 2015-2019 by Thomas Loimer ++ * Parts Copyright (c) 2015-2020 by Thomas Loimer + * + * Any party obtaining a copy of these files is granted, free of charge, a + * full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -83,7 +83,7 @@ bool bgspec = false; /* flag to say -g was specified */ + bool support_i18n = false; + #endif + char gif_transparent[20]="\0"; /* GIF transp color hex name (e.g. #ff00dd) */ +-char papersize[20]; /* paper size */ ++char papersize[]; /* paper size */ + char boundingbox[64]; /* boundingbox */ + char lang[40]; /* selected output language */ + RGB background; /* background (if specified by -g) */ +diff --git a/fig2dev/fig2dev.h b/fig2dev/fig2dev.h +index 9b6515f..25cc86b 100644 +--- a/fig2dev/fig2dev.h ++++ b/fig2dev/fig2dev.h +@@ -3,7 +3,7 @@ + * Copyright (c) 1991 by Micah Beck + * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + * Parts Copyright (c) 1989-2015 by Brian V. Smith +- * Parts Copyright (c) 2015-2019 by Thomas Loimer ++ * Parts Copyright (c) 2015-2020 by Thomas Loimer + * + * Any party obtaining a copy of these files is granted, free of charge, a + * full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -101,7 +101,7 @@ extern bool bgspec; /* flag to say -g was specified */ + extern bool support_i18n; + #endif + extern char gif_transparent[];/* GIF transp color hex name (e.g. #ff00dd) */ +-extern char papersize[]; /* paper size */ ++extern char papersize[16]; /* paper size */ + extern char boundingbox[]; /* boundingbox */ + extern char lang[]; /* selected output language */ + extern const char *Fig_color_names[]; /* hex names for Fig colors */ +diff --git a/fig2dev/read.c b/fig2dev/read.c +index 9500091..aea9537 100644 +--- a/fig2dev/read.c ++++ b/fig2dev/read.c +@@ -3,7 +3,7 @@ + * Copyright (c) 1991 by Micah Beck + * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + * Parts Copyright (c) 1989-2015 by Brian V. Smith +- * Parts Copyright (c) 2015-2019 by Thomas Loimer ++ * Parts Copyright (c) 2015-2020 by Thomas Loimer + * + * Any party obtaining a copy of these files is granted, free of charge, a + * full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -45,28 +45,34 @@ extern F_arrow *make_arrow(int type, int style, /* arrow.c */ + User_color user_colors[MAX_USR_COLS]; /* fig2dev.h */ + int user_col_indx[MAX_USR_COLS]; /* fig2dev.h */ + int num_usr_cols; /* fig2dev.h */ +-int num_object; /* read1_3.c */ + /* flags, psfonts.h, genps.c */ + int v2_flag; /* Protocol V2.0 or higher */ + int v21_flag; /* Protocol V2.1 or higher */ + int v30_flag; /* Protocol V3.0 or higher */ + int v32_flag; /* Protocol V3.2 or higher */ + +-static void read_colordef(void); +-static F_ellipse *read_ellipseobject(void); +-static F_line *read_lineobject(FILE *fp); +-static F_text *read_textobject(FILE *fp); +-static F_spline *read_splineobject(FILE *fp); +-static F_arc *read_arcobject(FILE *fp); +-static F_compound *read_compoundobject(FILE *fp); ++static void read_colordef(char *line, int line_no); ++static F_ellipse *read_ellipseobject(char *line, int line_no); ++static F_line *read_lineobject(FILE *fp, char **restrict line, ++ size_t *line_len, int *line_no); ++static F_text *read_textobject(FILE *fp, char **restrict line, ++ size_t *line_len, int *line_no); ++static F_spline *read_splineobject(FILE *fp, char **restrict line, ++ size_t *line_len, int *line_no); ++static F_arc *read_arcobject(FILE *fp, char **restrict line, ++ size_t *line_len, int *line_no); ++static F_compound *read_compoundobject(FILE *fp, char **restrict line, ++ size_t *line_len, int *line_no); + static F_comment *attach_comments(void); +-static void count_lines_correctly(FILE *fp); +-static void init_pats_used(void); +-static int read_objects(FILE *fp, F_compound *obj); +-static int get_line(FILE *fp); +-static void skip_line(FILE *fp); +-static int backslash_count(char cp[], int start); +-static int save_comment(void); ++static void count_lines_correctly(FILE *fp, int *line_no); ++static void init_pats_used(void); ++static int read_objects(FILE *fp, F_compound *obj); ++static ssize_t get_line(FILE *fp, char **restrict line, ++ size_t *line_len, int *line_no); ++static void skip_line(FILE *fp); ++static ptrdiff_t backslash_count(const char *restrict cp, ++ ptrdiff_t start); ++ + static char Err_incomp[] = "Incomplete %s object at line %d."; + static char Err_invalid[] = "Invalid %s object at line %d."; + static char Err_arrow[] = "Invalid %s arrow at line %d."; +@@ -77,9 +83,6 @@ static char Err_arrow[] = "Invalid %s arrow at line %d."; + /* max number of comments that can be stored with each object */ + #define MAXCOMMENTS 100 + +-static int gif_colnum = 0; +-static char buf[BUFSIZ]; +-static int line_no = 0; + static char *comments[MAXCOMMENTS]; /* comments saved for current object */ + static int numcom; /* current comment index */ + static bool com_alloc = false; /* whether or not the comment array +@@ -148,7 +151,6 @@ readfp_fig(FILE *fp, F_compound *obj) + char c; + int i, status; + +- num_object = 0; + num_usr_cols = 0; + init_pats_used(); + +@@ -157,15 +159,14 @@ readfp_fig(FILE *fp, F_compound *obj) + /* initialize the comment array */ + if (!com_alloc) + for (i = 0; i < MAXCOMMENTS; ++i) +- comments[i] = (char *) NULL; ++ comments[i] = (char *)NULL; + com_alloc = true; +- memset((char*)obj, '\0', COMOBJ_SIZE); ++ memset((void *)obj, '\0', COMOBJ_SIZE); + + /* read first character to see if it is "#" (#FIG 1.4 and newer) */ + c = fgetc(fp); + if (feof(fp)) + return -2; +- memset((char*)obj, '\0', COMOBJ_SIZE); + /* put the character back */ + ungetc(c, fp); + if (c == '#') +@@ -185,25 +186,30 @@ read_objects(FILE *fp, F_compound *obj) + F_spline *s, *ls = NULL; + F_arc *a, *la = NULL; + F_compound *c, *lc = NULL; +- int object, coord_sys, len; +- +- memset((char*)obj, '\0', COMOBJ_SIZE); +- +- (void) fgets(buf, BUFSIZ, fp); /* get the version line */ +- if (strncmp(buf, "#FIG ", 5)) { +- put_msg("Incorrect format string in first line of input file."); ++ bool objects = false; ++ int object, coord_sys; ++ int line_no; ++ int gif_colnum = 0; ++ char *line; ++ char buf[16]; ++ size_t line_len = 256; ++ ++ /* Get the 15 chars of the first line. ++ Use fgets(), because get_line() would store the line as a comment */ ++ if (fgets(buf, sizeof buf, fp) == NULL) { ++ put_msg("Could not read input file."); + return -1; + } ++ /* seek to the end of the first line */ ++ if (strchr(buf, '\n') == NULL) { ++ int c; ++ do ++ c = fgetc(fp); ++ while (c != '\n' && c != EOF); ++ } + +- /* remove newline and any carriage return (from a PC, perhaps) */ +- len = strlen(buf); +- if (buf[len-1] == '\n') { +- if (buf[len-2] == '\r') +- buf[len-2] = '\0'; +- else +- buf[len-1] = '\0'; +- } else { /* fgets() only stops at newline and end-of-file */ +- put_msg("File is truncated at first line."); ++ if (strncmp(buf, "#FIG ", 5)) { ++ put_msg("Incorrect format string in first line of input file."); + return -1; + } + +@@ -211,49 +217,65 @@ read_objects(FILE *fp, F_compound *obj) + v2_flag = (!strncmp(buf, "#FIG 2", 6) || !strncmp(buf, "#FIG 3", 6)); + /* v21_flag is for version 2.1 or higher */ + v21_flag = (!strncmp(buf, "#FIG 2.1", 8) || !strncmp(buf, "#FIG 3", 6)); +- /* version 2.2 was only beta - 3.0 is the official release (they are identical) */ ++ /* version 2.2 was only beta - 3.0 is the official release ++ (they are identical) */ + v30_flag = (!strncmp(buf, "#FIG 3", 6) || !strncmp(buf, "#FIG 2.2", 8)); +- /* version 3.2 contains paper size, magnif, multiple page and transparent color +- in Fig file */ ++ /* version 3.2 contains paper size, magnif, multiple page ++ and transparent color in Fig file */ + v32_flag = (!strncmp(buf, "#FIG 3.2", 8)); + if (strncmp(&buf[5], PACKAGE_VERSION, 3) > 0) { +- put_msg("Fig file format (%s) newer than this version of fig2dev (%s), exiting", +- &buf[5], PACKAGE_VERSION); +- exit(1); ++ put_msg("Fig file format (%s) newer than this version of fig2dev (%s), exiting", ++ &buf[5], PACKAGE_VERSION); ++ exit(EXIT_FAILURE); ++ } ++ ++ if ((v2_flag | v21_flag | v30_flag | v32_flag) == 0 && ++ strncmp(buf, "#FIG 1.4", 8)) { ++ put_msg("Cannot determine fig file format from string '%s'.", ++ &buf[5]); ++ exit(EXIT_FAILURE); ++ } ++ ++ if ((line = malloc(line_len)) == NULL) { ++ put_msg(Err_mem); ++ return -1; + } + ++ line_no = 1; + if (v30_flag) { + /* read the orientation spec (landscape/portrait) */ +- line_no=1; +- if (get_line(fp) < 0) { ++ if (get_line(fp, &line, &line_len, &line_no) < 0) { + put_msg("File is truncated at landscape/portrait specification."); ++ free(line); + return -1; + } + /* but set only if the user didn't specify the orientation + on the command line */ + if (!orientspec) +- landscape = !strncasecmp(buf,"land",4); ++ landscape = !strncasecmp(line, "land", 4); + + /* now read the metric/inches spec OR centering spec */ +- if (get_line(fp) < 0) { ++ if (get_line(fp, &line, &line_len, &line_no) < 0) { + put_msg("File is truncated at metric/inches or centering specification."); ++ free(line); + return -1; + } + /* read justification spec */ +- if ((strncasecmp(buf,"center",6) == 0) || +- (strncasecmp(buf,"flush",5) == 0)) { ++ if ((strncasecmp(line, "center", 6) == 0) || ++ (strncasecmp(line, "flush", 5) == 0)) { + /* but set only if user didn't specify it */ + if (!centerspec) +- center = strncasecmp(buf,"flush",5); ++ center = strncasecmp(line, "flush", 5); + /* now read metric/inches spec */ +- if (get_line(fp) < 0) { ++ if (get_line(fp, &line, &line_len, &line_no) < 0) { + put_msg("File is truncated at metric/inches specification."); ++ free(line); + return -1; + } + } + /* read metric/inches spec */ + /* if metric, scale magnification to correct for xfig display error */ +- if (strncasecmp(buf,"metric", 6) == 0) { ++ if (strncasecmp(line, "metric", 6) == 0) { + metric = 1; + } else { + metric = 0; +@@ -261,56 +283,67 @@ read_objects(FILE *fp, F_compound *obj) + + /* new stuff in 3.2 */ + if (v32_flag) { +- char *p; + /* read the paper size */ +- if (get_line(fp) < 0) { ++ if (get_line(fp, &line, &line_len, &line_no) < 0) { + put_msg("File is truncated at paper size specification."); ++ free(line); + return -1; + } + if (!paperspec) { +- strcpy(papersize,buf); +- /* and truncate at first blank, if any */ +- if ((p=strchr(papersize,' '))) ++ char *p; ++ /* truncate at first blank, if any */ ++ if ((p = strchr(line, ' '))) + *p = '\0'; ++ if (strlen(line) + 1 > sizeof papersize) { ++ put_msg("Invalid paper size specification at line %d: %s", ++ line_no, line); ++ free(line); ++ return -1; ++ } ++ strcpy(papersize, line); + } + + /* read the magnification */ +- if (get_line(fp) < 0) { ++ if (get_line(fp, &line, &line_len, &line_no) < 0) { + put_msg("File is truncated at magnification specification."); ++ free(line); + return -1; + } +- /* if the users hasn't specified a magnification on the command line, +- use the one in the file */ ++ /* if the users hasn't specified a magnification on ++ the command line, use the one in the file */ + if (!magspec) { +- mag = atof(buf)/100.0; ++ mag = atof(line)/100.0; + if (mag <= 0.) + mag = 1.; + fontmag = mag; + } + + /* read the multiple page flag */ +- if (get_line(fp) < 0) { ++ if (get_line(fp, &line, &line_len, &line_no) < 0) { + put_msg("File is truncated at multiple page specification."); ++ free(line); + return -1; + } + if (!multispec) +- multi_page = (strncasecmp(buf,"multiple",8) == 0); ++ multi_page = (strncasecmp(line, "multiple", 8) == 0); + + /* Read the GIF transparent color. */ +- if (get_line(fp) < 0) { ++ if (get_line(fp, &line, &line_len, &line_no) < 0) { + put_msg("File is truncated at transparent color specification."); ++ free(line); + return -1; + } + if (!transspec) { +- gif_colnum = atoi(buf); ++ gif_colnum = atoi(line); + if (gif_colnum < -3) { + put_msg("Invalid color number for transparent color."); ++ free(line); + return -1; + } + /* if standard color, get the name from the array */ + /* for user colors, wait till we've read in the file to get the value */ + if (gif_colnum < NUM_STD_COLS && gif_colnum >= 0) +- strcpy(gif_transparent,Fig_color_names[gif_colnum]); ++ strcpy(gif_transparent, Fig_color_names[gif_colnum]); + } + } + } else { +@@ -329,17 +362,20 @@ read_objects(FILE *fp, F_compound *obj) + } + + /* now read for resolution and coord_sys (coord_sys is not used) */ +- if (get_line(fp) < 0) { ++ if (get_line(fp, &line, &line_len, &line_no) < 0) { + put_msg("File is truncated at resolution specification."); ++ free(line); + return -1; + } +- if (sscanf(buf,"%lf%d\n", &ppi, &coord_sys) != 2) { ++ if (sscanf(line, "%lf%d", &ppi, &coord_sys) != 2) { + put_msg("Incomplete resolution information at line %d.", line_no); ++ free(line); + return -1; + } + if (ppi <= 0.) { + put_msg("Invalid resolution information (%g) at line %d.", + ppi, line_no); ++ free(line); + return -1; + } + +@@ -349,24 +385,28 @@ read_objects(FILE *fp, F_compound *obj) + /* attach any comments found thus far to the whole figure */ + obj->comments = attach_comments(); + +- while (get_line(fp) > 0) { +- if (sscanf(buf, "%d", &object) != 1) { ++ while (get_line(fp, &line, &line_len, &line_no) > 0) { ++ if (sscanf(line, "%d", &object) != 1) { + put_msg("Incorrect format at line %d.", line_no); ++ free(line); + return -1; + } + switch (object) { + case OBJ_COLOR_DEF: +- read_colordef(); +- if (num_object) { ++ if (objects) { + put_msg("Color definitions must come before other objects (line %d).", + line_no); +- return (-1); ++ free(line); ++ return -1; + } +- ++num_usr_cols; ++ read_colordef(line, line_no); + break; + case OBJ_POLYLINE : +- if ((l = read_lineobject(fp)) == NULL) ++ if ((l = read_lineobject(fp, &line, &line_len, &line_no)) == ++ NULL) { ++ free(line); + return -1; ++ } + #ifdef V4_0 + if ((l->pic != NULL) && (l->pic->figure != NULL)) { + if (lc) +@@ -388,79 +428,97 @@ read_objects(FILE *fp, F_compound *obj) + ll = (ll->next = l); + else + ll = obj->lines = l; +- num_object++; ++ objects = true; + break; + #endif /* V4_0 */ + case OBJ_SPLINE : +- if ((s = read_splineobject(fp)) == NULL) { ++ if ((s = read_splineobject(fp, &line, &line_len, &line_no)) ++ == NULL) { ++ free(line); + return -1; +- } ++ } + if (v32_flag){ /* s is a line */ + if (ll) + ll = (ll->next = (F_line *) s); + else + ll = obj->lines = (F_line *) s; +- num_object++; ++ objects = true; + break; + } + if (ls) + ls = (ls->next = s); + else + ls = obj->splines = s; +- num_object++; ++ objects = true; + break; + case OBJ_ELLIPSE : +- if ((e = read_ellipseobject()) == NULL) ++ if ((e = read_ellipseobject(line, line_no)) == NULL) { ++ free(line); + return -1; ++ } + if (le) + le = (le->next = e); + else + le = obj->ellipses = e; +- num_object++; ++ objects = true; + break; + case OBJ_ARC : +- if ((a = read_arcobject(fp)) == NULL) ++ if ((a = read_arcobject(fp, &line, &line_len, &line_no)) == ++ NULL) { ++ free(line); + return -1; ++ } + if (la) + la = (la->next = a); + else + la = obj->arcs = a; +- num_object++; ++ objects = true; + break; + case OBJ_TEXT : +- if ((t = read_textobject(fp)) == NULL) ++ if ((t = read_textobject(fp, &line, &line_len, &line_no)) == ++ NULL) { ++ free(line); + return -1; ++ } + if (lt) + lt = (lt->next = t); + else + lt = obj->texts = t; +- num_object++; ++ objects = true; + break; + case OBJ_COMPOUND : +- if ((c = read_compoundobject(fp)) == NULL) ++ if ((c = read_compoundobject(fp, &line, &line_len,&line_no)) ++ == NULL) { ++ free(line); + return -1; ++ } + if (lc) + lc = (lc->next = c); + else + lc = obj->compounds = c; +- num_object++; ++ objects = true; + break; + default : + put_msg("Incorrect object code at line %d.", line_no); ++ free(line); + return -1; + } /* switch */ +- } /* while (get_line(fp)) */ ++ } /* while (get_line(...)) */ ++ free(line); + + /* if user color was requested for GIF transparent color, get the + rgb values from the user color array now that we've read them in */ + if (gif_colnum >= NUM_STD_COLS) { + int i; +- for (i=0; i MAX_USR_COLS) ++ num_usr_cols = MAX_USR_COLS; ++ for (i=0; i < num_usr_cols; ++i) + if (user_col_indx[i] == gif_colnum) + break; + if (i < num_usr_cols) +- sprintf(gif_transparent,"#%2x%2x%2x", +- user_colors[i].r,user_colors[i].g,user_colors[i].b); ++ sprintf(gif_transparent, "#%2x%2x%2x", ++ user_colors[i].r, user_colors[i].g, user_colors[i].b); + } + + if (feof(fp)) +@@ -474,55 +532,72 @@ read_objects(FILE *fp, F_compound *obj) + } /* read_objects */ + + static void +-read_colordef(void) ++read_colordef(char *line, int line_no) + { +- int c; +- unsigned int r,g,b; +- +- if ((sscanf(buf, "%*d %d #%2x%2x%2x", &c, &r, &g, &b) != 4) || +- (c < NUM_STD_COLS)) { +- buf[strlen(buf)-1]='\0'; /* remove the newline */ +- put_msg("Invalid color definition: %s, setting to black (#00000).",buf); +- r=g=b=0; +- } +- user_col_indx[num_usr_cols] = c; +- user_colors[num_usr_cols].r = r; +- user_colors[num_usr_cols].g = g; +- user_colors[num_usr_cols].b = b; ++ int c; ++ unsigned int r,g,b; ++ ++ if (num_usr_cols >= MAX_USR_COLS) { ++ if (num_usr_cols == MAX_USR_COLS) { ++ put_msg("Maximum number of color definitions (%d) exceeded at line %d.", ++ MAX_USR_COLS, line_no); ++ ++num_usr_cols; ++ } ++ /* ignore additional colors */ ++ return; ++ } ++ if (sscanf(line, "%*d %d #%2x%2x%2x", &c, &r, &g, &b) != 4) { ++ if (c >= NUM_STD_COLS && c < NUM_STD_COLS + MAX_USR_COLS) { ++ put_msg("Invalid color definition at line %d: %s, setting to black (#00000).", ++ line_no, line); ++ r = g = b = 0; ++ } else { ++ put_msg("User color number at line %d out of range (%d), should be between %d and %d.", ++ line_no, c, NUM_STD_COLS, ++ NUM_STD_COLS + MAX_USR_COLS - 1); ++ return; ++ } ++ } ++ user_col_indx[num_usr_cols] = c; ++ user_colors[num_usr_cols].r = r; ++ user_colors[num_usr_cols].g = g; ++ user_colors[num_usr_cols].b = b; ++ ++num_usr_cols; + } + + static void +-fix_and_note_color(int *color) ++fix_and_note_color(int *color, int line_no) + { +- int i; +- if (*color < DEFAULT) { +- put_msg("Invalid color number %d at line %d, using default color.", +- *color, line_no); +- *color = DEFAULT; +- return; +- } +- if (*color < NUM_STD_COLS) { +- if (*color >= BLACK_COLOR) { +- std_color_used[*color] = true; ++ int i; ++ ++ if (*color < DEFAULT) { ++ put_msg("Invalid color number %d at line %d, using default color.", ++ *color, line_no); ++ *color = DEFAULT; ++ return; + } +- return; +- } +- for (i=0; i= BLACK_COLOR) { ++ std_color_used[*color] = true; ++ } + return; + } +- put_msg("Cannot locate user color %d, using default color at line %d.", +- *color, line_no); +- *color = DEFAULT; +- return; ++ for (i = 0; i < MIN(num_usr_cols, MAX_USR_COLS); ++i) ++ if (*color == user_col_indx[i]) { ++ *color = i + NUM_STD_COLS; ++ return; ++ } ++ put_msg("Cannot locate user color %d, using default color at line %d.", ++ *color, line_no); ++ *color = DEFAULT; ++ return; + } + + static void +-note_fill(int fill, int *color) ++note_fill(int fill, int *color, int line_no) + { + if (fill != UNFILLED) { +- fix_and_note_color(color); ++ fix_and_note_color(color, line_no); + if (fill >= NUMSHADES + NUMTINTS) { + pattern_used[fill - NUMSHADES - NUMTINTS] = true; + pats_used = true; +@@ -531,7 +606,7 @@ note_fill(int fill, int *color) + } + + static F_arc * +-read_arcobject(FILE *fp) ++read_arcobject(FILE *fp, char **restrict line, size_t *line_len, int *line_no) + { + F_arc *a; + int n, fa, ba; +@@ -548,7 +623,7 @@ read_arcobject(FILE *fp) + a->back_arrow = NULL; + a->next = NULL; + if (v30_flag) { +- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d%lf%lf%d%d%d%d%d%d\n", ++ n = sscanf(*line,"%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d%lf%lf%d%d%d%d%d%d", + &a->type, &a->style, &a->thickness, + &a->pen_color, &a->fill_color, &a->depth, &a->pen, &a->fill_style, + &a->style_val, &a->cap_style, +@@ -558,7 +633,7 @@ read_arcobject(FILE *fp) + &a->point[1].x, &a->point[1].y, + &a->point[2].x, &a->point[2].y); + } else { +- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d%d%lf%lf%d%d%d%d%d%d\n", ++ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%lf%d%d%d%lf%lf%d%d%d%d%d%d", + &a->type, &a->style, &a->thickness, + &a->pen_color, &a->depth, &a->pen, &a->fill_style, + &a->style_val, &a->direction, &fa, &ba, +@@ -570,45 +645,45 @@ read_arcobject(FILE *fp) + a->cap_style = 0; /* butt line cap */ + } + if ((v30_flag && n != 21) || (!v30_flag && n != 19)) { +- put_msg(Err_incomp, "arc", line_no); ++ put_msg(Err_incomp, "arc", *line_no); + free(a); + return NULL; + } + a->thickness *= round(THICK_SCALE); + a->fill_style = FILL_CONVERT(a->fill_style); + if (INVALID_ARC(a)) { +- put_msg(Err_invalid, "arc", line_no); ++ put_msg(Err_invalid, "arc", *line_no); + free(a); + return NULL; + } +- fix_and_note_color(&a->pen_color); +- note_fill(a->fill_style, &a->fill_color); ++ fix_and_note_color(&a->pen_color, *line_no); ++ note_fill(a->fill_style, &a->fill_color, *line_no); + if (fa) { +- if (get_line(fp) < 0 || +- sscanf(buf, "%d%d%lf%lf%lf", ++ if (get_line(fp, line, line_len, line_no) < 0 || ++ sscanf(*line, "%d%d%lf%lf%lf", + &type, &style, &thickness, &wid, &ht) != 5) { +- put_msg(Err_incomp, "arc", line_no); ++ put_msg(Err_incomp, "arc", *line_no); + free(a); + return NULL; + } + if ((a->for_arrow = make_arrow(type, style, thickness, wid, ht)) + == NULL) { +- put_msg(Err_arrow, "forward", line_no); ++ put_msg(Err_arrow, "forward", *line_no); + free(a); + return NULL; + } + } + if (ba) { +- if (get_line(fp) < 0 || +- sscanf(buf, "%d%d%lf%lf%lf", ++ if (get_line(fp, line, line_len, line_no) < 0 || ++ sscanf(*line, "%d%d%lf%lf%lf", + &type, &style, &thickness, &wid, &ht) != 5) { +- put_msg(Err_incomp, "arc", line_no); ++ put_msg(Err_incomp, "arc", *line_no); + free(a); + return NULL; + } + if ((a->back_arrow = make_arrow(type, style, thickness, wid, ht)) + == NULL) { +- put_msg(Err_arrow, "backward", line_no); ++ put_msg(Err_arrow, "backward", *line_no); + free(a); + return NULL; + } +@@ -618,7 +693,8 @@ read_arcobject(FILE *fp) + } + + static F_compound * +-read_compoundobject(FILE *fp) ++read_compoundobject(FILE *fp, char **restrict line, size_t *line_len, ++ int *line_no) + { + F_arc *a, *la = NULL; + F_ellipse *e, *le = NULL; +@@ -638,22 +714,23 @@ read_compoundobject(FILE *fp) + com->next = NULL; + com->comments = attach_comments(); /* attach any comments */ + +- n = sscanf(buf, "%*d%d%d%d%d\n", &com->nwcorner.x, &com->nwcorner.y, ++ n = sscanf(*line, "%*d%d%d%d%d", &com->nwcorner.x, &com->nwcorner.y, + &com->secorner.x, &com->secorner.y); + if (n != 4) { +- put_msg(Err_incomp, "compound", line_no); ++ put_msg(Err_incomp, "compound", *line_no); + free(com); + return NULL; + } +- while (get_line(fp) > 0) { +- if (sscanf(buf, "%d", &object) != 1) { +- put_msg(Err_incomp, "compound", line_no); ++ while (get_line(fp, line, line_len, line_no) > 0) { ++ if (sscanf(*line, "%d", &object) != 1) { ++ put_msg(Err_incomp, "compound", *line_no); + free_compound(&com); + return NULL; +- } ++ } + switch (object) { + case OBJ_POLYLINE : +- if ((l = read_lineobject(fp)) == NULL) { ++ if ((l = read_lineobject(fp, line, line_len, line_no)) == ++ NULL) { + return NULL; + } + #ifdef V4_0 +@@ -674,7 +751,8 @@ read_compoundobject(FILE *fp) + #endif /* V4_0 */ + break; + case OBJ_SPLINE : +- if ((s = read_splineobject(fp)) == NULL) { ++ if ((s = read_splineobject(fp, line, line_len, line_no)) == ++ NULL) { + return NULL; + } + if (v32_flag){ /* s is a line */ +@@ -690,7 +768,7 @@ read_compoundobject(FILE *fp) + ls = com->splines = s; + break; + case OBJ_ELLIPSE : +- if ((e = read_ellipseobject()) == NULL) { ++ if ((e = read_ellipseobject(*line, *line_no)) == NULL) { + return NULL; + } + if (le) +@@ -699,7 +777,8 @@ read_compoundobject(FILE *fp) + le = com->ellipses = e; + break; + case OBJ_ARC : +- if ((a = read_arcobject(fp)) == NULL) { ++ if ((a = read_arcobject(fp, line, line_len, line_no)) == ++ NULL) { + return NULL; + } + if (la) +@@ -708,7 +787,8 @@ read_compoundobject(FILE *fp) + la = com->arcs = a; + break; + case OBJ_TEXT : +- if ((t = read_textobject(fp)) == NULL) { ++ if ((t = read_textobject(fp, line, line_len, line_no)) == ++ NULL) { + return NULL; + } + if (lt) +@@ -717,7 +797,8 @@ read_compoundobject(FILE *fp) + lt = com->texts = t; + break; + case OBJ_COMPOUND : +- if ((c = read_compoundobject(fp)) == NULL) { ++ if ((c = read_compoundobject(fp, line, line_len, line_no)) ++ == NULL) { + return NULL; + } + if (lc) +@@ -728,7 +809,7 @@ read_compoundobject(FILE *fp) + case OBJ_END_COMPOUND : + return com; + default : +- put_msg("Wrong object code at line %d", line_no); ++ put_msg("Wrong object code at line %d", *line_no); + return NULL; + } /* switch */ + } +@@ -739,7 +820,7 @@ read_compoundobject(FILE *fp) + } + + static F_ellipse * +-read_ellipseobject(void) ++read_ellipseobject(char *line, int line_no) + { + F_ellipse *e; + int n; +@@ -749,7 +830,7 @@ read_ellipseobject(void) + e->pen = 0; + e->next = NULL; + if (v30_flag) { +- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d\n", ++ n = sscanf(line, "%*d%d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d", + &e->type, &e->style, &e->thickness, + &e->pen_color, &e->fill_color, &e->depth, &e->pen, &e->fill_style, + &e->style_val, &e->direction, &e->angle, +@@ -758,7 +839,7 @@ read_ellipseobject(void) + &e->start.x, &e->start.y, + &e->end.x, &e->end.y); + } else { +- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d\n", ++ n = sscanf(line, "%*d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d", + &e->type, &e->style, &e->thickness, + &e->pen_color, &e->depth, &e->pen, &e->fill_style, + &e->style_val, &e->direction, &e->angle, +@@ -773,7 +854,7 @@ read_ellipseobject(void) + free(e); + return NULL; + } +- fix_and_note_color(&e->pen_color); ++ fix_and_note_color(&e->pen_color, line_no); + e->thickness *= round(THICK_SCALE); + e->fill_style = FILL_CONVERT(e->fill_style); + if (e->radiuses.x < 0) +@@ -785,7 +866,7 @@ read_ellipseobject(void) + free(e); + return NULL; + } +- note_fill(e->fill_style, &e->fill_color); ++ note_fill(e->fill_style, &e->fill_color, line_no); + e->comments = attach_comments(); /* attach any comments */ + return e; + } +@@ -804,8 +885,9 @@ read_ellipseobject(void) + */ + static int + sanitize_lineobject( +- F_line *l, /* the line */ +- F_point *p /* the last point of the line */ ++ F_line *l, /* the line */ ++ F_point *p, /* the last point of the line */ ++ int line_no + ) + { + F_point *q; +@@ -912,7 +994,7 @@ sanitize_lineobject( + } + + static F_line * +-read_lineobject(FILE *fp) ++read_lineobject(FILE *fp, char **restrict line, size_t *line_len, int *line_no) + { + F_line *l; + F_point *o = NULL, *p, *q; +@@ -933,40 +1015,38 @@ read_lineobject(FILE *fp) + l->pic = NULL; + l->comments = NULL; + +- sscanf(buf,"%*d%d",&l->type); /* get the line type */ ++ sscanf(*line, "%*d%d", &l->type); /* get the line type */ + + radius_flag = v30_flag || v21_flag || (v2_flag && l->type == T_ARC_BOX); + if (radius_flag) { + if (v30_flag) { +- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d%d%d", ++ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d%d%d", + &l->type,&l->style,&l->thickness,&l->pen_color,&l->fill_color, + &l->depth,&l->pen,&l->fill_style,&l->style_val, + &l->join_style,&l->cap_style, + &l->radius,&fa,&ba,&npts); + } else { +- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d%d", +- &l->type,&l->style,&l->thickness,&l->pen_color, +- &l->depth,&l->pen,&l->fill_style,&l->style_val,&l->radius,&fa, &ba); ++ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%lf%d%d%d", ++ &l->type,&l->style,&l->thickness,&l->pen_color,&l->depth, ++ &l->pen,&l->fill_style,&l->style_val,&l->radius,&fa, &ba); + l->fill_color = l->pen_color; + } + } + /* old format uses pen for radius of arc-box corners */ + else { +- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d", ++ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%lf%d%d", + &l->type,&l->style,&l->thickness,&l->pen_color, + &l->depth,&l->pen,&l->fill_style,&l->style_val,&fa,&ba); + l->fill_color = l->pen_color; +- if (l->type == T_ARC_BOX) +- { +- l->radius = (int) l->pen; ++ if (l->type == T_ARC_BOX) { ++ l->radius = l->pen; + l->pen = 0; +- } +- else ++ } else + l->radius = 0; + } + if ((!radius_flag && n!=10) || + (radius_flag && ((!v30_flag && n!=11)||(v30_flag && n!=15)))) { +- put_msg(Err_incomp, "line", line_no); ++ put_msg(Err_incomp, "line", *line_no); + free(l); + return NULL; + } +@@ -974,45 +1054,47 @@ read_lineobject(FILE *fp) + l->thickness *= round(THICK_SCALE); + l->fill_style = FILL_CONVERT(l->fill_style); + if (INVALID_LINE(l)) { +- put_msg(Err_invalid, "line", line_no); ++ put_msg(Err_invalid, "line", *line_no); + free(l); + return NULL; + } +- note_fill(l->fill_style, &l->fill_color); +- fix_and_note_color(&l->pen_color); ++ note_fill(l->fill_style, &l->fill_color, *line_no); ++ fix_and_note_color(&l->pen_color, *line_no); + if (fa) { +- if (get_line(fp) < 0 || +- sscanf(buf, "%d%d%lf%lf%lf", ++ if (get_line(fp, line, line_len, line_no) < 0 || ++ sscanf(*line, "%d%d%lf%lf%lf", + &type, &style, &thickness, &wid, &ht) != 5) { +- put_msg(Err_incomp, "line", line_no); ++ put_msg(Err_incomp, "line", *line_no); + free(l); + return NULL; + } + if ((l->for_arrow = make_arrow(type, style, thickness, wid, ht)) + == NULL) { +- put_msg(Err_arrow, "forward", line_no); ++ put_msg(Err_arrow, "forward", *line_no); + free(l); + return NULL; + } + } + if (ba) { +- if (get_line(fp) < 0 || +- sscanf(buf, "%d%d%lf%lf%lf", ++ if (get_line(fp, line, line_len, line_no) < 0 || ++ sscanf(*line, "%d%d%lf%lf%lf", + &type, &style, &thickness, &wid, &ht) != 5) { +- put_msg(Err_incomp, "line", line_no); ++ put_msg(Err_incomp, "line", *line_no); + free_linestorage(l); + return NULL; + } + if ((l->back_arrow = make_arrow(type, style, thickness, wid, ht)) + == NULL) { +- put_msg(Err_arrow, "backward", line_no); ++ put_msg(Err_arrow, "backward", *line_no); + free_linestorage(l); + return NULL; + } + } + if (l->type == T_PIC_BOX) { +- char file[BUFSIZ], *c; ++ char *file, *c; ++ int pos; + size_t len; ++ ssize_t chars; + + if ((Pic_malloc(l->pic)) == NULL) { + free(l); +@@ -1026,21 +1108,22 @@ read_lineobject(FILE *fp) + XpmCreateXpmImageFromBuffer("", &l->pic->xpmimage, NULL); + #endif + +- /* %[^\n]: really, read until first '\0' in buf */ +- if (get_line(fp) < 0 || sscanf(buf, "%d %[^\n]", +- &l->pic->flipped, file) != 2) { +- put_msg(Err_incomp, "picture", line_no); +- free(l); +- return NULL; ++ if ((chars = get_line(fp, line, line_len, line_no)) < 0 || ++ sscanf(*line, "%d %n", &l->pic->flipped, &pos) != 1) { ++ put_msg(Err_incomp, "picture", *line_no); ++ free(l); ++ return NULL; + } ++ file = *line + pos; ++ len = chars - pos; /* strlen(file) */ ++ + /* if there is a path in the .fig filename, and the path of the + * imported picture filename is NOT absolute, prepend the + * .fig file path to it + */ + if (from && (c = strrchr(from, '/')) && file[0] != '/') { +- if ((l->pic->file = malloc((size_t)(c - from + 2) + +- (len = strlen(file)))) == +- NULL) { ++ if ((l->pic->file = malloc((size_t)(c - from + 2) + len)) == ++ NULL) { + put_msg(Err_mem); + free(l); /* Points not read yet. */ + return NULL; +@@ -1049,8 +1132,8 @@ read_lineobject(FILE *fp) + memcpy(l->pic->file + (c - from + 1), file, len + 1); + } else { + /* either absolute picture path or no path in .fig filename */ +- l->pic->file = malloc(len = strlen(file) + 1); +- memcpy(l->pic->file, file, len); ++ l->pic->file = malloc(len + 1); ++ memcpy(l->pic->file, file, len + 1); + } + } + +@@ -1062,9 +1145,9 @@ read_lineobject(FILE *fp) + p->next = NULL; + + /* read first point of line */ +- ++line_no; ++ ++(*line_no); + if (fscanf(fp, "%d%d", &p->x, &p->y) != 2) { +- put_msg(Err_incomp, "line", line_no); ++ put_msg(Err_incomp, "line", *line_no); + free_linestorage(l); + return NULL; + } +@@ -1072,9 +1155,9 @@ read_lineobject(FILE *fp) + if (!v30_flag) + npts = 1000000; + for (--npts; npts > 0; --npts) { +- count_lines_correctly(fp); ++ count_lines_correctly(fp, line_no); + if (fscanf(fp, "%d%d", &x, &y) != 2) { +- put_msg(Err_incomp, "line", line_no); ++ put_msg(Err_incomp, "line", *line_no); + free_linestorage(l); + return NULL; + } +@@ -1103,7 +1186,7 @@ read_lineobject(FILE *fp) + l->last[1].y = o->y; + } + +- if (sanitize_lineobject(l, p)) { ++ if (sanitize_lineobject(l, p, *line_no)) { + free_linestorage(l); + return NULL; + } +@@ -1115,7 +1198,8 @@ read_lineobject(FILE *fp) + } + + static F_spline * +-read_splineobject(FILE *fp) ++read_splineobject(FILE *fp, char **restrict line, size_t *line_len, ++ int *line_no) + { + F_spline *s; + F_line *l; +@@ -1137,58 +1221,58 @@ read_splineobject(FILE *fp) + s->next = NULL; + + if (v30_flag) { +- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d", ++ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d", + &s->type, &s->style, &s->thickness, + &s->pen_color, &s->fill_color, + &s->depth, &s->pen, &s->fill_style, &s->style_val, + &s->cap_style, &fa, &ba, &npts); + } else { +- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d", ++ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%lf%d%d", + &s->type, &s->style, &s->thickness, &s->pen_color, + &s->depth, &s->pen, &s->fill_style, &s->style_val, &fa, &ba); + s->fill_color = s->pen_color; + s->cap_style = 0; /* butt line cap */ + } + if ((v30_flag && n != 13) || (!v30_flag && n != 10)) { +- put_msg(Err_incomp, "spline", line_no); ++ put_msg(Err_incomp, "spline", *line_no); + free(s); + return NULL; + } + s->thickness *= round(THICK_SCALE); + s->fill_style = FILL_CONVERT(s->fill_style); + if (INVALID_SPLINE(s)) { +- put_msg(Err_invalid, "spline", line_no); ++ put_msg(Err_invalid, "spline", *line_no); + free(s); + return NULL; + } +- note_fill(s->fill_style, &s->fill_color); +- fix_and_note_color(&s->pen_color); ++ note_fill(s->fill_style, &s->fill_color, *line_no); ++ fix_and_note_color(&s->pen_color, *line_no); + if (fa) { +- if (get_line(fp) < 0 || +- sscanf(buf, "%d%d%lf%lf%lf", ++ if (get_line(fp, line, line_len, line_no) < 0 || ++ sscanf(*line, "%d%d%lf%lf%lf", + &type, &style, &thickness, &wid, &ht) != 5) { +- put_msg(Err_incomp, "spline", line_no); ++ put_msg(Err_incomp, "spline", *line_no); + free(s); + return NULL; + } + if ((s->for_arrow = make_arrow(type, style, thickness, wid, ht)) + == NULL) { +- put_msg(Err_arrow, "forward", line_no); ++ put_msg(Err_arrow, "forward", *line_no); + free(s); + return NULL; + } + } + if (ba) { +- if (get_line(fp) < 0 || +- sscanf(buf, "%d%d%lf%lf%lf", ++ if (get_line(fp, line, line_len, line_no) < 0 || ++ sscanf(*line, "%d%d%lf%lf%lf", + &type, &style, &thickness, &wid, &ht) != 5) { +- put_msg(Err_incomp, "spline", line_no); ++ put_msg(Err_incomp, "spline", *line_no); + free_splinestorage(s); + return NULL; + } + if ((s->back_arrow = make_arrow(type, style, thickness, wid, ht)) + == NULL) { +- put_msg(Err_arrow, "backward", line_no); ++ put_msg(Err_arrow, "backward", *line_no); + free_splinestorage(s); + return NULL; + } +@@ -1196,9 +1280,9 @@ read_splineobject(FILE *fp) + + /* Read points */ + /* read first point of line */ +- ++line_no; ++ ++(*line_no); + if ((n = fscanf(fp, "%d%d", &x, &y)) != 2) { +- put_msg(Err_incomp, "spline", line_no); ++ put_msg(Err_incomp, "spline", *line_no); + free_splinestorage(s); + return NULL; + }; +@@ -1212,15 +1296,15 @@ read_splineobject(FILE *fp) + if (!v30_flag) + npts = 1000000; + if (npts < 2) { +- put_msg(Err_incomp, "spline", line_no); ++ put_msg(Err_incomp, "spline", *line_no); + free_splinestorage(s); + return NULL; + } + for (--npts; npts > 0; --npts) { + /* keep track of newlines for line counter */ +- count_lines_correctly(fp); ++ count_lines_correctly(fp, line_no); + if (fscanf(fp, "%d%d", &x, &y) != 2) { +- put_msg(Err_incomp, "spline", line_no); ++ put_msg(Err_incomp, "spline", *line_no); + free_splinestorage(s); + return NULL; + }; +@@ -1250,9 +1334,9 @@ read_splineobject(FILE *fp) + ptr = s->controls; + while (ptr) { /* read controls */ + /* keep track of newlines for line counter */ +- count_lines_correctly(fp); ++ count_lines_correctly(fp, line_no); + if ((n = fscanf(fp, "%lf", &control_s)) != 1) { +- put_msg(Err_incomp, "spline", line_no); ++ put_msg(Err_incomp, "spline", *line_no); + free_splinestorage(s); + return NULL; + } +@@ -1275,9 +1359,9 @@ read_splineobject(FILE *fp) + } + /* Read controls from older versions */ + /* keep track of newlines for line counter */ +- count_lines_correctly(fp); ++ count_lines_correctly(fp, line_no); + if ((n = fscanf(fp, "%lf%lf%lf%lf", &lx, &ly, &rx, &ry)) != 4) { +- put_msg(Err_incomp, "spline", line_no); ++ put_msg(Err_incomp, "spline", *line_no); + free_splinestorage(s); + return NULL; + } +@@ -1290,9 +1374,9 @@ read_splineobject(FILE *fp) + cp->rx = rx; cp->ry = ry; + while (--c) { + /* keep track of newlines for line counter */ +- count_lines_correctly(fp); ++ count_lines_correctly(fp, line_no); + if (fscanf(fp, "%lf%lf%lf%lf", &lx, &ly, &rx, &ry) != 4) { +- put_msg(Err_incomp, "spline", line_no); ++ put_msg(Err_incomp, "spline", *line_no); + cp->next = NULL; + free_splinestorage(s); + return NULL; +@@ -1315,13 +1399,37 @@ read_splineobject(FILE *fp) + return s; + } + ++static char * ++find_end(const char *str, int v30flag) ++{ ++ const char endmark[] = "\\001"; ++ char *end; ++ ++ if (v30flag) { ++ /* A string is terminated with the literal '\001', ++ and 8-bit characters may be represented as \xxx */ ++ end = strstr(str, endmark); ++ /* is this not '\\001', or '\\\\001', etc? */ ++ while (end && backslash_count(str, end - str) % 2 == 0) ++ end = strstr(end + 3, endmark); ++ } else { ++ /* The text object is terminated by a CONTROL-A. ++ If there is no CONTROL-A on this line, then this ++ must be a multi-line text object. */ ++ end = strchr(str, '\1'); ++ } ++ return end; ++} ++ ++ + static F_text * +-read_textobject(FILE *fp) ++read_textobject(FILE *fp, char **restrict line, size_t *line_len, int *line_no) + { + F_text *t; +- int n, ignore = 0; +- char s[BUFSIZ], s_temp[BUFSIZ], junk[2]; +- int more, len, l; ++ bool freestart = false; ++ int i, n; ++ char *end, *start; ++ size_t len; + + Text_malloc(t); + t->font = 0; +@@ -1329,32 +1437,101 @@ read_textobject(FILE *fp) + t->comments = NULL; + t->next = NULL; + +- if (v30_flag) { /* order of parms is more like other objects now, +- string is now terminated with the literal '\001', +- and 8-bit characters are represented as \xxx */ ++ n = sscanf(*line, "%*d%d%d%d%d%d%lf%lf%d%lf%lf%d%d %n", ++ &t->type, &t->color, &t->depth, &t->pen, &t->font, ++ &t->size, &t->angle, &t->flags, &t->height, &t->length, ++ &t->base_x, &t->base_y, &i); ++ if (n != 12) { ++ put_msg(Err_incomp, "text", *line_no); ++ free(t); ++ return NULL; ++ } ++ start = *line + i; ++ end = find_end(start, v30_flag); + +- n = sscanf(buf, "%*d%d%d%d%d%d%lf%lf%d%lf%lf%d%d%[^\n]", +- &t->type, &t->color, &t->depth, &t->pen, +- &t->font, &t->size, &t->angle, +- &t->flags, &t->height, &t->length, +- &t->base_x, &t->base_y, s); ++ if (end) { ++ *end = '\0'; ++ len = end - start; + } else { +- /* The text object is terminated by a CONTROL-A, so we read +- everything up to the CONTROL-A and then read that character. +- If we do not find the CONTROL-A on this line then this must +- be a multi-line text object and we will have to read more. */ +- +- n = sscanf(buf,"%*d%d%d%lf%d%d%d%lf%d%lf%lf%d%d%[^\1]%1[\1]", +- &t->type, &t->font, &t->size, &t->pen, +- &t->color, &t->depth, &t->angle, +- &t->flags, &t->height, &t->length, +- &t->base_x, &t->base_y, s, junk); ++ ssize_t chars; ++ char *next; ++ ++ len = strlen(start); ++ start[len++] = '\n'; /* put back the newline */ ++ ++ /* allocate plenty of space */ ++ next = malloc(len + BUFSIZ); ++ if (next == NULL) { ++ put_msg(Err_mem); ++ free(t); ++ return NULL; ++ } ++ memcpy(next, start, len); ++ ++ while ((chars = getline(line, line_len, fp)) != -1) { ++ ++(*line_no); ++ end = find_end(*line, v30_flag); ++ if (end) { ++ *end = '\0'; ++ next = realloc(next, len + end - *line + 1); ++ memcpy(next + len, *line, end - *line + 1); ++ len += end - *line; ++ break; ++ } else { ++ if (**line + chars - 1 == '\n' && chars > 1 && ++ **line + chars - 2 == '\r') ++ (*line)[chars-- - 2] = '\n'; ++ next = realloc(next, len + chars + 1); ++ memcpy(next + len, *line, chars + 1); ++ len += chars; ++ } ++ } ++ start = next; ++ freestart = true; ++ } ++ ++ /* convert any \xxx to characters */ ++ if (v30_flag && (end = strchr(start, '\\'))) { ++ unsigned char num; ++ char *c = start; ++ size_t l; ++ ++ len = end - start; ++ l = len; ++ while (c[l] != '\0') { ++ if (c[l] == '\\') { ++ /* convert 3 digit octal value */ ++ if (isdigit(c[l+1]) && c[l+2] != '\0' && ++ c[l+3] != '\0') { ++ if (sscanf(c+l+1, "%3hho", &num) != 1) { ++ put_msg("Error in parsing text string on line %d", ++ *line_no); ++ return NULL; ++ } ++ /* no check of unsigned char overflow */ ++ c[len++] = num; ++ l += 3; ++ } else { ++ /* an escaped char is un-escaped */ ++ c[len++] = c[++l]; ++ } ++ } else { ++ c[len++] = c[l]; ++ } ++ ++l; ++ } ++ c[len] = '\0'; /* terminate */ + } +- if ((n != 14) && (n != 13)) { +- put_msg(Err_incomp, "text", line_no); +- free(t); +- return NULL; ++ ++ t->cstring = malloc(len + 1); ++ if (t->cstring == NULL) { ++ put_msg(Err_mem); ++ free(t); ++ return NULL; + } ++ memcpy(t->cstring, start, len + 1); ++ if (freestart) ++ free(start); + + if (font_size != 0.0) { + /* scale length/height of text by ratio of requested font size to actual size */ +@@ -1364,89 +1541,6 @@ read_textobject(FILE *fp) + } + if (t->size <= 0.0) + t->size = (float) DEFAULT_FONT_SIZE; +- more = 0; +- if (!v30_flag && n == 13) +- more = 1; /* in older xfig there is more if ^A wasn't found yet */ +- else if (v30_flag) { /* in 3.0 there is more if \001 wasn't found */ +- len = strlen(s); +- if ((strcmp(&s[len-4],"\\001") == 0) && /* if we find '\000' */ +- !(backslash_count(s, len-5) % 2)) { /* and not '\\000' */ +- more = 0; /* then there are no more lines */ +- s[len-4]='\0'; /* and get rid of the '\001' */ +- } else { +- more = 1; +- s[len++]='\n'; /* put back the end of line char */ +- s[len] = '\0'; /* and terminate it */ +- } +- } +- if (more) { +- /* Read in the subsequent lines of the text if there are more */ +- do { +- ++line_no; /* As is done in get_line */ +- if (fgets(s_temp, BUFSIZ, fp) == NULL) +- break; +- len = strlen(s_temp)-1; /* ignore newline */ +- if (len > 0 && s_temp[len-1] == '\r') { /* strip any trailing CR */ +- s_temp[len-1] = '\0'; +- len--; +- } +- if (v30_flag) { +- if ((strncmp(&s_temp[len-4],"\\001",4) == 0) && +- !(backslash_count(s_temp, len-5) % 2)) { +- n=0; /* found the '\001', set n to stop */ +- s_temp[len-4]='\0'; /* and get rid of the '\001' */ +- } else { +- n=1; /* keep going (more lines) */ +- } +- } else { +- n = sscanf(buf, "%[^\1]%[\1]", s_temp, junk); +- } +- /* Safety check */ +- if (strlen(s)+1 + strlen(s_temp)+1 > BUFSIZ) { +- /* Too many characters. Ignore the rest. */ +- ignore = 1; +- } +- if (!ignore) +- strcat(s, s_temp); +- } while (n == 1); +- } +- +- if (v30_flag) { /* now convert any \xxx to ascii characters */ +- if (strchr(s,'\\')) { +- unsigned int num; +- len = strlen(s); +- for (l=0,n=0; l < len; ++l) { +- if (s[l]=='\\') { +- /* a backslash, see if a digit follows */ +- if (l < len && isdigit(s[l+1])) { +- /* yes, scan for 3 digit octal value */ +- if (sscanf(&s[l+1],"%3o",&num)!=1) { +- put_msg("Error in parsing text string on line %d", +- line_no); +- return NULL; +- } +- buf[n++]= (unsigned char) num; /* put char in */ +- l += 3; /* skip over digits */ +- } else { +- buf[n++] = s[++l]; /* some other escaped character */ +- } +- } else { +- buf[n++] = s[l]; /* ordinary character */ +- } +- } +- buf[n]='\0'; /* terminate */ +- strcpy(s,buf); /* copy back to s */ +- } +- } +- if (strlen(s) == 0) +- (void)strcpy(s, " "); +- t->cstring = calloc((unsigned)(strlen(s)), sizeof(char)); +- if (NULL == t->cstring) { +- put_msg(Err_mem); +- free(t); +- return NULL; +- } +- (void)strcpy(t->cstring, s+1); + + if (!v21_flag && (t->font == 0 || t->font == DEFAULT)) + t->flags = ((t->flags != DEFAULT) ? t->flags : 0) +@@ -1457,11 +1551,11 @@ read_textobject(FILE *fp) + | PSFONT_TEXT; + + if (INVALID_TEXT(t)) { +- put_msg(Err_invalid, "text", line_no); ++ put_msg(Err_invalid, "text", *line_no); + free_text(&t); + return NULL; + } +- fix_and_note_color(&t->color); ++ fix_and_note_color(&t->color, *line_no); + t->comments = attach_comments(); /* attach any comments */ + return t; + } +@@ -1469,18 +1563,19 @@ read_textobject(FILE *fp) + + /* count consecutive backslashes backwards */ + +-static int +-backslash_count(char cp[], int start) ++static ptrdiff_t ++backslash_count(const char *restrict cp, ptrdiff_t start) + { +- int i, count = 0; ++ ptrdiff_t i; ++ ptrdiff_t count = 0; + +- for(i=start; i>=0; i--) { +- if (cp[i] == '\\') +- count++; +- else +- break; +- } +- return count; ++ for(i = start; i >= 0; --i) { ++ if (cp[i] == '\\') ++ ++count; ++ else ++ break; ++ } ++ return count; + } + + /* attach comments in linked list */ +@@ -1509,54 +1604,63 @@ attach_comments(void) + return icomp; + } + ++/* save a comment line to be stored with the *subsequent* object */ ++ + static int +-get_line(FILE *fp) ++save_comment(char *restrict line, size_t len) + { +- int len; +- while (1) { +- if (NULL == fgets(buf, BUFSIZ, fp)) { +- return -1; ++ int i; ++ ++ /* skip too many comment lines */ ++ if (numcom == MAXCOMMENTS) ++ return 2; ++ ++ /* remove one leading blank from the comment, if there is one */ ++ i = 1; ++ if (line[i] == ' ') ++ i = 2; ++ ++ /* see if we've allocated space for this comment */ ++ if (comments[numcom]) ++ free(comments[numcom]); ++ if ((comments[numcom] = malloc(len + (1 - i))) == NULL) ++ return -1; ++ ++ strcpy(comments[numcom++], &line[i]); ++ return 1; ++} ++ ++static ssize_t ++get_line(FILE *fp, char **restrict line, size_t *line_len, int *line_no) ++{ ++ ssize_t chars; ++ ++ while ((chars = getline(line, line_len, fp)) != -1) { ++ ++(*line_no); ++ /* skip empty lines */ ++ if (**line == '\n' || (**line == '\r' && ++ chars == 2 && (*line)[1] == '\n')) ++ continue; ++ /* remove newline and possibly a carriage return */ ++ if ((*line)[chars-1] == '\n') { ++ chars -= (*line)[chars - 2] == '\r' ? 2 : 1; ++ (*line)[chars] = '\0'; + } +- ++line_no; +- if (*buf == '#') { /* save any comments */ +- if (save_comment() < 0) ++ /* save any comments */ ++ if (**line == '#') { ++ if (save_comment(*line, (size_t)chars) < 0) + return -1; +- /* skip empty lines */ +- } else if (*buf != '\n' || !(*buf == '\r' && buf[1] == '\n')) { +- len = strlen(buf); +- /* remove newline and possibly a carriage return */ +- if (buf[len-1] == '\n') +- buf[len - (buf[len-2] == '\r' ? 2 : 1)] = '\0'; +- return 1; ++ continue; + } ++ /* return the line */ ++ return chars; + } ++ /* chars == -1 */ ++ return chars; ++ /* getline() only fails with EINVAL, and probably ENOMEM from malloc(). ++ No use to check for errno. */ + } + +-/* save a comment line to be stored with the *subsequent* object */ +- +-static int +-save_comment(void) +-{ +- int i; +- +- /* skip too many comment lines */ +- if (numcom == MAXCOMMENTS) +- return 2; +- i=strlen(buf); +- /* see if we've allocated space for this comment */ +- if (comments[numcom]) +- free(comments[numcom]); +- if ((comments[numcom] = malloc(i+1)) == NULL) +- return -1; +- /* remove any newline */ +- if (buf[i-1] == '\n') +- buf[i-1] = '\0'; +- i=1; +- if (buf[1] == ' ') /* remove one leading blank from the comment, if there is one */ +- i=2; +- strcpy(comments[numcom++], &buf[i]); +- return 1; +-} + + /* skip to the end of the current line and any subsequent blank lines */ + +@@ -1714,15 +1818,15 @@ static int pop() { + */ + + static void +-count_lines_correctly(FILE *fp) ++count_lines_correctly(FILE *fp, int *line_no) + { + int cc; + do { +- cc = getc(fp); +- if (cc == '\n') { +- ++line_no; +- cc=getc(fp); +- } ++ cc = getc(fp); ++ if (cc == '\n') { ++ ++(*line_no); ++ cc=getc(fp); ++ } + } while (cc == ' ' || cc == '\t'); + ungetc(cc,fp); + } +diff --git a/fig2dev/read1_3.c b/fig2dev/read1_3.c +index 64c7819..3b7a263 100644 +--- a/fig2dev/read1_3.c ++++ b/fig2dev/read1_3.c +@@ -2,8 +2,8 @@ + * Fig2dev: Translate Fig code to various Devices + * Copyright (c) 1991 by Micah Beck + * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul +- * Parts Copyright (c) 1989-2012 by Brian V. Smith +- * Parts Copyright (c) 2015-2019 by Thomas Loimer ++ * Parts Copyright (c) 1989-2015 by Brian V. Smith ++ * Parts Copyright (c) 2015-2020 by Thomas Loimer + * + * Any party obtaining a copy of these files is granted, free of charge, a + * full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -51,8 +51,6 @@ + + extern F_arrow *forward_arrow(void), *backward_arrow(void); + extern int figure_modified; +-//extern int line_no; +-extern int num_object; + + static F_ellipse *read_ellipseobject(FILE *fp); + static F_line *read_lineobject(FILE *fp); +@@ -103,7 +101,6 @@ read_1_3_objects(FILE *fp, F_compound *obj) + ll = (ll->next = l); + else + ll = obj->lines = l; +- num_object++; + break; + case OBJ_SPLINE : + if ((s = read_splineobject(fp)) == NULL) return(-1); +@@ -111,7 +108,6 @@ read_1_3_objects(FILE *fp, F_compound *obj) + ls = (ls->next = s); + else + ls = obj->splines = s; +- num_object++; + break; + case OBJ_ELLIPSE : + if ((e = read_ellipseobject(fp)) == NULL) return(-1); +@@ -119,7 +115,6 @@ read_1_3_objects(FILE *fp, F_compound *obj) + le = (le->next = e); + else + le = obj->ellipses = e; +- num_object++; + break; + case OBJ_ARC : + if ((a = read_arcobject(fp)) == NULL) return(-1); +@@ -127,7 +122,6 @@ read_1_3_objects(FILE *fp, F_compound *obj) + la = (la->next = a); + else + la = obj->arcs = a; +- num_object++; + break; + case OBJ_TEXT : + if ((t = read_textobject(fp)) == NULL) return(-1); +@@ -135,7 +129,6 @@ read_1_3_objects(FILE *fp, F_compound *obj) + lt = (lt->next = t); + else + lt = obj->texts = t; +- num_object++; + break; + case OBJ_COMPOUND : + if ((c = read_compoundobject(fp)) == NULL) return(-1); +@@ -143,7 +136,6 @@ read_1_3_objects(FILE *fp, F_compound *obj) + lc = (lc->next = c); + else + lc = obj->compounds = c; +- num_object++; + break; + default: + put_msg("Incorrect object code %d", object); +diff --git a/fig2dev/tests/read.at b/fig2dev/tests/read.at +index 4ef8747..9b34bfb 100644 +--- a/fig2dev/tests/read.at ++++ b/fig2dev/tests/read.at +@@ -2,7 +2,7 @@ dnl Fig2dev: Translate Fig code to various Devices + dnl Copyright (c) 1991 by Micah Beck + dnl Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + dnl Parts Copyright (c) 1989-2015 by Brian V. Smith +-dnl Parts Copyright (c) 2015-2019 by Thomas Loimer ++dnl Parts Copyright (c) 2015-2020 by Thomas Loimer + dnl + dnl Any party obtaining a copy of these files is granted, free of charge, a + dnl full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -14,7 +14,7 @@ dnl party to do so, with the only requirement being that the above copyright + dnl and this permission notice remain intact. + + dnl read.at +-dnl Author: Thomas Loimer, 2017-2019 ++dnl Author: Thomas Loimer, 2017-2020 + + + AT_BANNER([Sanitize and harden input.]) +@@ -279,7 +279,7 @@ AT_CHECK([fig2dev -L box <comments, " %"); + fprintf(tfp,"%% %%\n"); + } ++ if (figname_buf) ++ free(figname_buf); + } + + int +@@ -549,6 +553,8 @@ hatchindex(index) + static void + getrgb(int color, int *r, int *g, int *b) + { ++ if (color < 0) /* DEFAULT color is black */ ++ color = 0; + if (color < NUM_STD_COLS) { + *r = stdcols[color].r * 255.; + *g = stdcols[color].g * 255.; +diff --git a/fig2dev/dev/genge.c b/fig2dev/dev/genge.c +index 8caabf1..c2ab712 100644 +--- a/fig2dev/dev/genge.c ++++ b/fig2dev/dev/genge.c +@@ -52,7 +52,8 @@ static void genge_ctl_spline(F_spline *s); + /* color mapping */ + /* xfig ge */ + +-static int GE_COLORS[] = { 1, /* black black */ ++static int GE_COLORS[] = { 1, /* DEFAULT == black */ ++ 1, /* black black */ + 8, /* blue blue */ + 7, /* green green */ + 6, /* cyan cyan */ +@@ -434,7 +435,7 @@ back_arrow(F_line *l) + static void + set_color(int col) + { +- fprintf(tfp,"c%02d ",GE_COLORS[col]); ++ fprintf(tfp,"c%02d ",GE_COLORS[col + 1]); + } + + /* set fill if there is a fill style */ +@@ -443,7 +444,7 @@ static void + set_fill(int style, int color) + { + if (style != UNFILLED) +- fprintf(tfp,"C%02d ",GE_COLORS[color]); ++ fprintf(tfp,"C%02d ",GE_COLORS[color + 1]); + } + + /* +diff --git a/fig2dev/tests/data/line.fig b/fig2dev/tests/data/line.fig +index e033b12..bfc4976 100644 +--- a/fig2dev/tests/data/line.fig ++++ b/fig2dev/tests/data/line.fig +@@ -7,5 +7,5 @@ A9 + Single + -2 + 1200 2 +-2 1 0 3 0 7 50 -1 -1 0.0 0 0 -1 0 0 3 ++2 1 0 3 -1 7 50 -1 -1 0.0 0 0 -1 0 0 3 + 50 50 500 50 500 200 +diff --git a/fig2dev/tests/output.at b/fig2dev/tests/output.at +index 9a1bc45..79788cc 100644 +--- a/fig2dev/tests/output.at ++++ b/fig2dev/tests/output.at +@@ -261,3 +261,13 @@ AT_CHECK([fig2dev -L tikz -P big1.fig big1.tex && \ + latex -halt-on-error big1.tex && latex -halt-on-error big2.tex + ], 0, ignore) + AT_CLEANUP ++ ++AT_BANNER([Test other output languages.]) ++ ++AT_SETUP([allow default color in ge, cgm output, #72, #73]) ++AT_KEYWORDS(cgm ge) ++AT_CHECK([fig2dev -L cgm $srcdir/data/line.fig ++], 0, ignore) ++AT_CHECK([fig2dev -L ge $srcdir/data/line.fig ++], 0, ignore) ++AT_CLEANUP +-- +2.31.1 + diff --git a/SOURCES/0010-CVE-2020-21683.patch b/SOURCES/0010-CVE-2020-21683.patch new file mode 100644 index 0000000..dfe1434 --- /dev/null +++ b/SOURCES/0010-CVE-2020-21683.patch @@ -0,0 +1,25 @@ +Subject: [PATCH] Fix pstricks fill with non-solid default color + +In the pstricks output, filling an area with the shaded or tinted default color +is now equivalent to filling with shaded or tinted black color. +--- + fig2dev/dev/genpstricks.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fig2dev/dev/genpstricks.c b/fig2dev/dev/genpstricks.c +index cf49207..40ea577 100644 +--- a/fig2dev/dev/genpstricks.c ++++ b/fig2dev/dev/genpstricks.c +@@ -1856,7 +1856,8 @@ format_options(char *options, char *prefix, char *postfix, char *sqrb_init, + else if (fill_style <= 40) + /* shade or tint fill */ + sprintf(tmps, "fillstyle=solid,fillcolor=%s", +- shade_or_tint_name_after_declare_color(tmpc, fill_style, fill_color)); ++ shade_or_tint_name_after_declare_color(tmpc, fill_style, ++ fill_color == DEFAULT ? CT_BLACK : fill_color)); + else { + char *type = 0, *ps; + int angle = 0; +-- +2.31.1 + diff --git a/SOURCES/0011-CVE-2020-21680.patch b/SOURCES/0011-CVE-2020-21680.patch new file mode 100644 index 0000000..c34bdc7 --- /dev/null +++ b/SOURCES/0011-CVE-2020-21680.patch @@ -0,0 +1,55 @@ +Subject: [PATCH] Allow arrows with zero length on arcs + +Use the tangent, not a secant, for short arrows on arcs. +--- + fig2dev/bound.c | 9 ++++----- + fig2dev/tests/output.at | 8 ++++++++ + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/fig2dev/bound.c b/fig2dev/bound.c +index ce7f4d1..9e997b7 100644 +--- a/fig2dev/bound.c ++++ b/fig2dev/bound.c +@@ -1095,16 +1095,15 @@ compute_arcarrow_angle(double x1, double y1, double x2, double y2, + r=sqrt(dx*dx+dy*dy); + h = (double) arrow->ht; + /* lines are made a little thinner in set_linewidth */ +- thick = (arrow->thickness <= THICK_SCALE) ? +- 0.5* arrow->thickness : +- arrow->thickness - THICK_SCALE; ++ thick = arrow->thickness <= THICK_SCALE ? ++ 0.5 * arrow->thickness : arrow->thickness - THICK_SCALE; + /* lpt is the amount the arrowhead extends beyond the end of the line */ + lpt = thick/2.0/(arrow->wid/h/2.0); + /* add this to the length */ + h += lpt; + +- /* radius too small for this method, use normal method */ +- if (h > 2.0*r) { ++ /* secant would be too large or too small */ ++ if (h > 2.0*r || h < 0.01*r) { + arc_tangent_int(x1,y1,x2,y2,direction,x,y); + return; + } +diff --git a/fig2dev/tests/output.at b/fig2dev/tests/output.at +index 79788cc..9150dbe 100644 +--- a/fig2dev/tests/output.at ++++ b/fig2dev/tests/output.at +@@ -175,6 +175,14 @@ AT_CHECK([fig2dev -L pict2e -P big1.fig big1.tex && \ + ], 0, ignore) + AT_CLEANUP + ++AT_SETUP([accept arc arrows with zero height, ticket #74]) ++AT_KEYWORDS(pict2e) ++AT_CHECK([fig2dev -L pict2e < +Date: Fri, 3 Sep 2021 08:15:34 +0200 +Subject: [PATCH] Reject ASCII NUL anywhere in the input + +The input is read in line by line, stored in a buffer and processed further +with sscanf(). Embedded NUL characters ('\0') would already disturb sscanf(), +and nowhere does the code expect NUL characters. Therefore, detect NUL while +reading the input, and exit with an error message when NUL is found anywere. +Fixes ticket #80. +--- + CHANGES | 4 ++++ + fig2dev/read.c | 21 +++++++++++++++++++-- + fig2dev/tests/data/text_w_ascii0.fig | 12 ++++++++++++ + fig2dev/tests/read.at | 16 ++++++++++++++++ + 4 files changed, 51 insertions(+), 2 deletions(-) + create mode 100644 fig2dev/tests/data/text_w_ascii0.fig + +diff --git a/CHANGES b/CHANGES +index 4a414fa..f1bbbc3 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -6,6 +6,10 @@ Patchlevel Xx (Xxx 20xx) + + BUGS FIXED: + Ticket numbers refer to https://sourceforge.net/p/mcj/tickets/#. ++ o Fix ticket #81. ++ o Do not allow ASCII NUL anywhere in input. Fixes ticket #80. ++ o Use getline() to improve input scanning. ++ Fixes tickets #58, #59, #61, #62, #67, #78, #79. + o Correctly scan embedded pdfs for /MediaBox value. + o Convert polygons having too few points to polylines. Ticket #56. + o Reject huge arrow types causing integer overflow. Ticket #57. +diff --git a/fig2dev/read.c b/fig2dev/read.c +index aea9537..6e47f2d 100644 +--- a/fig2dev/read.c ++++ b/fig2dev/read.c +@@ -200,8 +200,14 @@ read_objects(FILE *fp, F_compound *obj) + put_msg("Could not read input file."); + return -1; + } +- /* seek to the end of the first line */ +- if (strchr(buf, '\n') == NULL) { ++ ++ /* check for embedded '\0' */ ++ if (strlen(buf) < sizeof buf - 1 && buf[strlen(buf) - 1] != '\n') { ++ put_msg("ASCII NUL ('\\0') character within the first line."); ++ exit(EXIT_FAILURE); ++ /* seek to the end of the first line ++ (the only place, where '\0's are tolerated) */ ++ } else if (buf[strlen(buf) - 1] != '\n') { + int c; + do + c = fgetc(fp); +@@ -1399,6 +1405,15 @@ read_splineobject(FILE *fp, char **restrict line, size_t *line_len, + return s; + } + ++static void ++exit_on_ascii_NUL(const char *restrict line, size_t chars, int line_no) ++{ ++ if (strlen(line) < (size_t)chars) { ++ put_msg("ASCII NUL ('\\0') in line %d.", line_no); ++ exit(EXIT_FAILURE); ++ } ++} ++ + static char * + find_end(const char *str, int v30flag) + { +@@ -1470,6 +1485,7 @@ read_textobject(FILE *fp, char **restrict line, size_t *line_len, int *line_no) + + while ((chars = getline(line, line_len, fp)) != -1) { + ++(*line_no); ++ exit_on_ascii_NUL(*line, chars, *line_no); + end = find_end(*line, v30_flag); + if (end) { + *end = '\0'; +@@ -1641,6 +1657,7 @@ get_line(FILE *fp, char **restrict line, size_t *line_len, int *line_no) + if (**line == '\n' || (**line == '\r' && + chars == 2 && (*line)[1] == '\n')) + continue; ++ exit_on_ascii_NUL(*line, chars, *line_no); + /* remove newline and possibly a carriage return */ + if ((*line)[chars-1] == '\n') { + chars -= (*line)[chars - 2] == '\r' ? 2 : 1; +diff --git a/fig2dev/tests/data/text_w_ascii0.fig b/fig2dev/tests/data/text_w_ascii0.fig +new file mode 100644 +index 0000000..c0aa754 +--- /dev/null ++++ b/fig2dev/tests/data/text_w_ascii0.fig +@@ -0,0 +1,12 @@ ++#FIG 3.2 ++Landscape ++Center ++Inches ++Letter ++100.00 ++Single ++-2 ++1200 2 ++4 0 0 2 0 25 163 31 7 0 0 -1 1 0 2 ++ 0& 4 120 5 y\ 0 0 0^^^^^J^^^^^ÿÿ^^^^^^^^^^^^^^^^^^^^^^45 E\0I1y\001 ++#4 0 0 50 -1 -1 12 0.0 0 150 405 0 0 An ascii zero '\\0' here ->...and some more text following, with a certain amount of minimum characters\001 +diff --git a/fig2dev/tests/read.at b/fig2dev/tests/read.at +index 9b34bfb..60982b0 100644 +--- a/fig2dev/tests/read.at ++++ b/fig2dev/tests/read.at +@@ -406,6 +406,22 @@ EOF + ]) + AT_CLEANUP + ++AT_SETUP([allow tex font -1, ticket #81]) ++AT_KEYWORDS([pict2e tikz]) ++AT_DATA([text.fig], [FIG_FILE_TOP ++4 0 0 50 -1 -1 12 0.0 0 150 405 0 0 Text\001 ++]) ++AT_CHECK([fig2dev -L pict2e text.fig ++], 0, ignore) ++AT_CHECK([fig2dev -L tikz text.fig ++], 0, ignore) ++AT_CLEANUP ++ ++AT_SETUP([reject ASCII NUL ('\0') in input, ticket #80]) ++AT_KEYWORDS([read.c svg]) ++AT_CHECK([fig2dev -L svg $srcdir/data/text_w_ascii0.fig], 1, ignore, ignore) ++AT_CLEANUP ++ + AT_BANNER([Dynamically allocate picture file name.]) + + AT_SETUP([prepend fig file path to picture file name]) +-- +2.31.1 + diff --git a/SOURCES/0013-CVE-2020-21676.patch b/SOURCES/0013-CVE-2020-21676.patch new file mode 100644 index 0000000..df5af3f --- /dev/null +++ b/SOURCES/0013-CVE-2020-21676.patch @@ -0,0 +1,83 @@ +From 180cf468f8999cfb7245bac5b3be447aefa6c852 Mon Sep 17 00:00:00 2001 +From: Ondrej Dubaj +Date: Fri, 3 Sep 2021 08:24:19 +0200 +Subject: [PATCH] Reject text or ellipse angles beyond -2pi to 2pi, #76 + +In fact, generously extend the allowed range to -7 to 7. +Sane applications, e.g., xfig, certainly keep the angles within one revolution. +--- + CHANGES | 5 +++-- + fig2dev/object.h | 7 ++++--- + fig2dev/tests/read.at | 8 ++++++++ + 3 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/CHANGES b/CHANGES +index f1bbbc3..52daead 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -6,8 +6,9 @@ Patchlevel Xx (Xxx 20xx) + + BUGS FIXED: + Ticket numbers refer to https://sourceforge.net/p/mcj/tickets/#. +- o Fix ticket #81. +- o Do not allow ASCII NUL anywhere in input. Fixes ticket #80. ++ o Accept text and ellipse angles only within -2*pi to 2*pi. Fixes #76. ++ o Allow -1 as default TeX font, not only 0. Fixes #71, #75, #81. ++ o Do not allow ASCII NUL anywhere in input. Fixes #65, #68, #73, #80. + o Use getline() to improve input scanning. + Fixes tickets #58, #59, #61, #62, #67, #78, #79. + o Correctly scan embedded pdfs for /MediaBox value. +diff --git a/fig2dev/object.h b/fig2dev/object.h +index fe56bbb..8464010 100644 +--- a/fig2dev/object.h ++++ b/fig2dev/object.h +@@ -3,7 +3,7 @@ + * Copyright (c) 1991 by Micah Beck + * Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul + * Parts Copyright (c) 1989-2015 by Brian V. Smith +- * Parts Copyright (c) 2015-2019 by Thomas Loimer ++ * Parts Copyright (c) 2015-2020 by Thomas Loimer + * + * Any party obtaining a copy of these files is granted, free of charge, a + * full and unrestricted irrevocable, world-wide, paid up, royalty-free, +@@ -94,7 +94,8 @@ typedef struct f_ellipse { + #define INVALID_ELLIPSE(e) \ + e->type < T_ELLIPSE_BY_RAD || e->type > T_CIRCLE_BY_DIA || \ + COMMON_PROPERTIES(e) || (e->direction != 1 && e->direction != 0) || \ +- e->radiuses.x == 0 || e->radiuses.y == 0 ++ e->radiuses.x == 0 || e->radiuses.y == 0 || \ ++ e->angle < -7. || e->angle > 7. + + typedef struct f_arc { + int type; +@@ -243,7 +244,7 @@ typedef struct f_text { + t->type < T_LEFT_JUSTIFIED || t->type > T_RIGHT_JUSTIFIED || \ + t->font < DEFAULT || t->font > MAX_PSFONT || \ + t->flags < DEFAULT || t->flags >= 2 * HIDDEN_TEXT || \ +- t->height < 0 || t->length < 0 ++ t->height < 0 || t->length < 0 || t->angle < -7. || t->angle > 7. + + typedef struct f_control { + double lx, ly, rx, ry; /* used by older versions*/ +diff --git a/fig2dev/tests/read.at b/fig2dev/tests/read.at +index 60982b0..c53fbb9 100644 +--- a/fig2dev/tests/read.at ++++ b/fig2dev/tests/read.at +@@ -422,6 +422,14 @@ AT_KEYWORDS([read.c svg]) + AT_CHECK([fig2dev -L svg $srcdir/data/text_w_ascii0.fig], 1, ignore, ignore) + AT_CLEANUP + ++AT_SETUP([reject out of range text angle, ticket #76]) ++AT_CHECK([fig2dev -L pstricks < +Date: Mon, 20 Sep 2021 08:31:22 +0200 +Subject: [PATCH] Keep coordinates of spline controls within sane range + +--- + fig2dev/read.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/fig2dev/read.c b/fig2dev/read.c +index 6e47f2d..349a685 100644 +--- a/fig2dev/read.c ++++ b/fig2dev/read.c +@@ -1392,6 +1392,15 @@ read_splineobject(FILE *fp, char **restrict line, size_t *line_len, + cp->next = NULL; + free_splinestorage(s); + return NULL; ++ } ++ if (lx < INT_MIN || lx > INT_MAX || ly < INT_MIN || ly > INT_MAX || ++ rx < INT_MIN || rx > INT_MAX || ry < INT_MIN || ry > INT_MAX) { ++ /* do not care to clean up, we exit anyway ++ cp->next = NULL; ++ free_splinestorage(s); */ ++ put_msg("Spline control points out of range at line %d.", ++ *line_no); ++ exit(EXIT_FAILURE); + } + cq->lx = lx; cq->ly = ly; + cq->rx = rx; cq->ry = ry; +-- +2.31.1 + diff --git a/SOURCES/0015-CVE-2020-21532.patch b/SOURCES/0015-CVE-2020-21532.patch new file mode 100644 index 0000000..d308b7a --- /dev/null +++ b/SOURCES/0015-CVE-2020-21532.patch @@ -0,0 +1,134 @@ +From ae23821f5959ee7c6d10cf0219fad013d3469a6f Mon Sep 17 00:00:00 2001 +From: Ondrej Dubaj +Date: Tue, 21 Sep 2021 10:35:53 +0200 +Subject: [PATCH] Accept -1 as default TeX font, fixes ticket #81 + +The default for PostScript fonts is -1, for TeX fonts 0. Accepting -1 for TeX +fonts lead to out-of-bound read. Now, -1 for TeX fonts is converted to 0. + +Accept -1 TeX font in more places, fixes #71, #75 + +Continue the work started in commit [00cded]. Fix the fundamental issue of +tickets #71 and #75, which was hidden by commit [d70e4b]. +--- + fig2dev/dev/genpict2e.c | 9 +++++---- + fig2dev/dev/gentikz.c | 9 +++++---- + fig2dev/dev/texfonts.h | 14 +++++++++----- + fig2dev/tests/read.at | 14 +++++++++++++- + 4 files changed, 32 insertions(+), 14 deletions(-) + +diff --git a/fig2dev/dev/genpict2e.c b/fig2dev/dev/genpict2e.c +index 9f828f0..22daedd 100644 +--- a/fig2dev/dev/genpict2e.c ++++ b/fig2dev/dev/genpict2e.c +@@ -2222,11 +2222,12 @@ put_font(F_text *t) + } + + if (psfont_text(t)) +- fprintf(tfp, "\\usefont%s", +- texpsfonts[t->font <= MAX_PSFONT ? t->font + 1 : 0]); ++ fprintf(tfp, "\\usefont%s", texpsfonts[t->font <= MAX_PSFONT ? ++ t->font + 1 : 0]); + else +- fprintf(tfp, "\\normalfont%s ", +- texfonts[t->font <= MAX_FONT ? t->font : MAX_FONT - 1]); ++ /* Default psfont is -1, default texfont 0, also accept -1. */ ++ fprintf(tfp, "\\normalfont%s ", texfonts[t->font <= MAX_FONT ? ++ (t->font >= 0 ? t->font : 0) : MAX_FONT - 1]); + } + + void +diff --git a/fig2dev/dev/gentikz.c b/fig2dev/dev/gentikz.c +index 96ee41c..6d8aff4 100644 +--- a/fig2dev/dev/gentikz.c ++++ b/fig2dev/dev/gentikz.c +@@ -1771,11 +1771,12 @@ put_font(F_text *t) + } + + if (psfont_text(t)) +- fprintf(tfp, "\\usefont%s", +- texpsfonts[t->font <= MAX_PSFONT ? t->font + 1 : 0]); ++ fprintf(tfp, "\\usefont%s", texpsfonts[t->font <= MAX_PSFONT ? ++ t->font + 1 : 0]); + else +- fprintf(tfp, "\\normalfont%s ", +- texfonts[t->font <= MAX_FONT ? t->font : MAX_FONT - 1]); ++ /* Default psfont is -1, default texfont 0, also accept -1. */ ++ fprintf(tfp, "\\normalfont%s ", texfonts[t->font <= MAX_FONT ? ++ (t->font >= 0 ? t->font : 0) : MAX_FONT - 1]); + } + + /* +diff --git a/fig2dev/dev/texfonts.h b/fig2dev/dev/texfonts.h +index 89097f2..e5254b6 100644 +--- a/fig2dev/dev/texfonts.h ++++ b/fig2dev/dev/texfonts.h +@@ -35,17 +35,21 @@ extern char texfontsizes[]; + #define MAXFONTSIZE 42 + + #ifdef NFSS +-#define TEXFAMILY(F) (texfontfamily[((F) <= MAX_FONT) ? (F) : (MAX_FONT-1)]) +-#define TEXSERIES(F) (texfontseries[((F) <= MAX_FONT) ? (F) : (MAX_FONT-1)]) +-#define TEXSHAPE(F) (texfontshape[((F) <= MAX_FONT) ? (F) : (MAX_FONT-1)]) ++#define TEXFAMILY(F) texfontfamily[(F) <= MAX_FONT ? ((F) >= 0 ? (F) : 0) \ ++ : MAX_FONT-1] ++#define TEXSERIES(F) texfontseries[(F) <= MAX_FONT ? ((F) >= 0 ? (F) : 0) \ ++ : MAX_FONT-1] ++#define TEXSHAPE(F) texfontshape[(F) <= MAX_FONT ? ((F) >= 0 ? (F) : 0) \ ++ : MAX_FONT-1] + #endif +-#define TEXFONT(F) (texfontnames[((F) <= MAX_FONT) ? (F) : (MAX_FONT-1)]) ++#define TEXFONT(F) texfontnames[(F) <= MAX_FONT ? ((F) >= 0 ? (F) : 0) \ ++ : MAX_FONT-1] + + /* + #define TEXFONTSIZE(S) (texfontsizes[((S) <= MAXFONTSIZE) ? (int)(round(S))\ + : (MAXFONTSIZE-1)]) + */ +-#define TEXFONTSIZE(S) (((S) <= MAXFONTSIZE) ? texfontsizes[(int)(round(S))] : (S)) ++#define TEXFONTSIZE(S) ((S) <= MAXFONTSIZE ? texfontsizes[(int)round(S)] : (S)) + #define TEXFONTMAG(T) TEXFONTSIZE(T->size*(rigid_text(T) ? 1.0 : fontmag)) + + void setfigfont(F_text *text); /* genepic.c */ +diff --git a/fig2dev/tests/read.at b/fig2dev/tests/read.at +index c53fbb9..d85356b 100644 +--- a/fig2dev/tests/read.at ++++ b/fig2dev/tests/read.at +@@ -406,7 +406,7 @@ EOF + ]) + AT_CLEANUP + +-AT_SETUP([allow tex font -1, ticket #81]) ++AT_SETUP([allow tex font -1, tickets #71, #75, #81]) + AT_KEYWORDS([pict2e tikz]) + AT_DATA([text.fig], [FIG_FILE_TOP + 4 0 0 50 -1 -1 12 0.0 0 150 405 0 0 Text\001 +@@ -415,6 +415,8 @@ AT_CHECK([fig2dev -L pict2e text.fig + ], 0, ignore) + AT_CHECK([fig2dev -L tikz text.fig + ], 0, ignore) ++AT_CHECK([fig2dev -L mp text.fig ++], 0, ignore) + AT_CLEANUP + + AT_SETUP([reject ASCII NUL ('\0') in input, ticket #80]) +@@ -430,6 +432,16 @@ EOF + ], 1, ignore, ignore) + AT_CLEANUP + ++AT_SETUP([allow tex font -1, ticket #81]) ++AT_DATA([text.fig], [FIG_FILE_TOP ++4 0 0 50 -1 -1 12 0.0 0 150 405 0 0 Text\001 ++]) ++AT_CHECK([fig2dev -L pict2e text.fig ++], 0, ignore) ++AT_CHECK([fig2dev -L tikz text.fig ++], 0, ignore) ++AT_CLEANUP ++ + AT_BANNER([Dynamically allocate picture file name.]) + + AT_SETUP([prepend fig file path to picture file name]) +-- +2.31.1 + diff --git a/SOURCES/0016-CVE-2020-21531.patch b/SOURCES/0016-CVE-2020-21531.patch new file mode 100644 index 0000000..8a8be42 --- /dev/null +++ b/SOURCES/0016-CVE-2020-21531.patch @@ -0,0 +1,63 @@ +From d50ae523fcee5c2d4357bbd8ce5baeeb18d15a2c Mon Sep 17 00:00:00 2001 +From: Ondrej Dubaj +Date: Tue, 21 Sep 2021 10:42:50 +0200 +Subject: [PATCH] Reject out-of-range pattern + +--- + fig2dev/object.h | 2 +- + fig2dev/tests/read.at | 19 +++++++++++++++++-- + 2 files changed, 18 insertions(+), 3 deletions(-) + +diff --git a/fig2dev/object.h b/fig2dev/object.h +index 8464010..6830b13 100644 +--- a/fig2dev/object.h ++++ b/fig2dev/object.h +@@ -61,7 +61,7 @@ typedef struct f_comment { + o->style < SOLID_LINE || o->style > DASH_3_DOTS_LINE || \ + o->thickness < 0 || o->depth < 0 || o->depth > 999 || \ + o->fill_style < UNFILLED || \ +- o->fill_style > NUMSHADES + NUMTINTS + NUMPATTERNS || \ ++ o->fill_style >= NUMSHADES + NUMTINTS + NUMPATTERNS || \ + o->style_val < 0.0 + + typedef struct f_ellipse { +diff --git a/fig2dev/tests/read.at b/fig2dev/tests/read.at +index d85356b..7765805 100644 +--- a/fig2dev/tests/read.at ++++ b/fig2dev/tests/read.at +@@ -421,15 +421,30 @@ AT_CLEANUP + + AT_SETUP([reject ASCII NUL ('\0') in input, ticket #80]) + AT_KEYWORDS([read.c svg]) +-AT_CHECK([fig2dev -L svg $srcdir/data/text_w_ascii0.fig], 1, ignore, ignore) ++AT_CHECK([fig2dev -L svg $srcdir/data/text_w_ascii0.fig], ++1, ignore, [ASCII NUL ('\0') in line 11. ++]) + AT_CLEANUP + + AT_SETUP([reject out of range text angle, ticket #76]) ++AT_KEYWORDS([read.c pstricks]) + AT_CHECK([fig2dev -L pstricks < +Date: Thu, 23 Sep 2021 09:49:37 +0200 +Subject: [PATCH] Do not crash on incomplete, closed splines + +--- + fig2dev/trans_spline.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/fig2dev/trans_spline.c b/fig2dev/trans_spline.c +index 0905c79..60c54ad 100644 +--- a/fig2dev/trans_spline.c ++++ b/fig2dev/trans_spline.c +@@ -226,6 +226,12 @@ compute_closed_spline(F_spline *spline, float precision) + if (!init_point_array(300, 200)) + return NULL; + ++ if (!(spline->points /* p0 */ && spline->controls /* s0 */ && ++ spline->points->next /* p1 */ && spline->controls->next /* s1 */ && ++ spline->points->next->next && spline->controls->next->next/* p2, s2 */&& ++ spline->points->next->next->next && spline->controls->next->next->next)) ++ return NULL; ++ + INIT_CONTROL_POINTS(spline, p0, s0, p1, s1, p2, s2, p3, s3); + COPY_CONTROL_POINT(first, s_first, p0, s0); + +-- +2.31.1 + diff --git a/SOURCES/0018-exit-no-args.patch b/SOURCES/0018-exit-no-args.patch new file mode 100644 index 0000000..03b2652 --- /dev/null +++ b/SOURCES/0018-exit-no-args.patch @@ -0,0 +1,39 @@ +Subject: [PATCH] Exit correctly when invoked without arguments +https://sourceforge.net/p/mcj/fig2dev/ci/11fba42e388ff7d92f81518406429bdea0a6a3b3 + +--- + fig2dev/fig2dev.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/fig2dev/fig2dev.c b/fig2dev/fig2dev.c +index 62ec099..949671e 100644 +--- a/fig2dev/fig2dev.c ++++ b/fig2dev/fig2dev.c +@@ -161,9 +161,9 @@ static struct depth_opts { + + static char Usage[] = + #ifdef I18N +-"Usage:\n %s -hV\n %s -L language [-s size] [-m scale] [-j] [input [output]]\n"; ++"Usage:\n %1$s -hV\n %1$s -L language [-s size] [-m scale] [-j] [input [output]]\n"; + #else +- "Usage:\n %s -hV\n %s -L language [-s size] [-m scale] [input [output]]\n"; ++ "Usage:\n %1$s -hV\n %1$s -L language [-s size] [-m scale] [input [output]]\n"; + #endif + + static int parse_gridspec(char *string, float *numer, float *denom, +@@ -218,8 +218,10 @@ get_args(int argc, char *argv[]) + char *grid, *p; + float numer, denom; + +- if (argc == 1) +- fprintf(stderr, Usage, prog, prog); ++ if (argc == 1) { ++ fprintf(stderr, Usage, prog); ++ exit(EXIT_SUCCESS); ++ } + + /* print the version, for the comfort of the autotest tests */ + if (!strcmp(argv[1], "--version")) { +-- +2.31.1 + diff --git a/SPECS/transfig.spec b/SPECS/transfig.spec new file mode 100644 index 0000000..a4f7e73 --- /dev/null +++ b/SPECS/transfig.spec @@ -0,0 +1,405 @@ +Name: transfig +Version: 3.2.7b +Release: 10%{?dist} +Epoch: 1 +Summary: Utility for converting FIG files (made by xfig) to other formats +License: MIT +URL: https://sourceforge.net/projects/mcj/ +Source0: http://downloads.sourceforge.net/mcj/fig2dev-%{version}.tar.xz +# Patches from upstream for CVE-2019-19746 and CVE-2019-19797 + deps +Patch1: 0001-Embed-png-and-jpeg-images-unchanged-into-pdfs.patch +Patch2: 0002-Allow-fig-2-text-ending-with-multiple-A-ticket-55.patch +Patch3: 0003-Reject-huge-arrow-types-ticket-57.patch +Patch4: 0004-Convert-polygons-with-too-few-points-to-polylines.patch +Patch5: 0005-Correctly-scan-embedded-pdfs-for-MediaBox-value.patch +Patch6: 0006-fig2dev-version-prints-version-information.patch +Patch7: 0007-Use-getopt-from-standard-libraries-if-available.patch +Patch8: 0008-Replace-most-calls-to-fgets-by-getline-in-read.c.patch +Patch9: 0009-CVE-2020-21681-CVE-2020-21682.patch +Patch10: 0010-CVE-2020-21683.patch +Patch11: 0011-CVE-2020-21680.patch +Patch12: 0012-CVE-2020-21678-CVE-2020-21684.patch +Patch13: 0013-CVE-2020-21676.patch +Patch14: 0014-CVE-2020-21529.patch +Patch15: 0015-CVE-2020-21532.patch +Patch16: 0016-CVE-2020-21531.patch +Patch17: 0017-CVE-2021-32280.patch +Patch18: 0018-exit-no-args.patch + +Requires: ghostscript +Requires: bc +Requires: netpbm-progs + +BuildRequires: make +BuildRequires: gcc libtool +BuildRequires: libpng-devel +BuildRequires: libjpeg-devel +BuildRequires: libXpm-devel +BuildRequires: ghostscript + +%description +The transfig utility creates a makefile which translates FIG (created +by xfig) or PIC figures into a specified LaTeX graphics language (for +example, PostScript(TM)). Transfig is used to create TeX documents +which are portable (i.e., they can be printed in a wide variety of +environments). + +Install transfig if you need a utility for translating FIG or PIC +figures into certain graphics languages. + + +%prep +%autosetup -p1 -n fig2dev-%{version} +autoreconf -i +# Fix the manpage not being in UTF-8 +iconv -f ISO-8859-15 -t UTF-8 man/fig2dev.1.in -o fig2dev.1.in.new +touch -r man/fig2dev.1.in fig2dev.1.in.new +mv fig2dev.1.in.new man/fig2dev.1.in + + +%build +%configure --enable-transfig +%make_build + + +%install +%make_install + + +%files +%doc CHANGES transfig/doc/manual.pdf +%{_bindir}/transfig +%{_bindir}/fig2dev +%{_bindir}/fig2ps2tex +%{_bindir}/pic2tpic +%{_datadir}/fig2dev/i18n/*.ps +%{_mandir}/man1/*.1.gz + + +%changelog +* Mon Oct 18 2021 Ondrej Dubaj - 1:3.2.7b-10 +- Exit correctly when invoked without arguments (#2015001) + +* Thu Sep 23 2021 Ondrej Dubaj - 1:3.2.7b-9 +- Fixed CVE-2021-32280 (#2006830) + +* Mon Sep 20 2021 Ondrej Dubaj - 1:3.2.7b-8 +- Fixed CVE-2020-21529 (#2005518) +- Fixed CVE-2020-21532 (#2006007) +- Fixed CVE-2020-21531 (#2006002) + +* Mon Aug 30 2021 Ondrej Dubaj - 1:3.2.7b-7 +- Fixed CVE-2020-21681 (#1998350) +- Fixed CVE-2020-21683 (#1998594) +- Fixed CVE-2020-21680 (#1998306) +- Fixed CVE-2020-21684 (#2000747) +- Fixed CVE-2020-21678 (#2000741) +- Fixed CVE-2020-21676 (#2000751) +- Fixed CVE-2020-21682 (#2000738) + +* Tue Aug 10 2021 Mohan Boddu - 1:3.2.7b-6 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Fri Apr 16 2021 Mohan Boddu - 1:3.2.7b-5 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Wed Jan 27 2021 Fedora Release Engineering - 1:3.2.7b-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Wed Jul 29 2020 Fedora Release Engineering - 1:3.2.7b-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Fri Jan 31 2020 Fedora Release Engineering - 1:3.2.7b-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Wed Jan 15 2020 Hans de Goede - 1:3.2.7b-1 +- New upstream release 3.2.7b +- Add patch fixing CVE-2019-19746 (rhbz#1787040) +- Add patch fixing CVE-2019-19797 (rhbz#1786726) + +* Sat Jul 27 2019 Fedora Release Engineering - 1:3.2.7a-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Tue Jun 18 2019 Zbigniew Jędrzejewski-Szmek - 1:3.2.7a-2 +- Add BR: ghostscript to fix ghostscript detection (#1720868) + +* Thu Jun 06 2019 Ondrej Dubaj - 1:3.2.7a-1 +- Updated to version 3.2.7a + +* Sun Feb 03 2019 Fedora Release Engineering - 1:3.2.6a-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Jul 16 2018 Honza Horak - 1:3.2.6a-5 +- Remove license GPLv3+ + +* Sun Jul 15 2018 Honza Horak - 1:3.2.6a-4 +- Add license GPLv3+ + +* Sat Jul 14 2018 Fedora Release Engineering - 1:3.2.6a-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Fri Feb 09 2018 Fedora Release Engineering - 1:3.2.6a-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Tue Nov 21 2017 Hans de Goede - 3.2.6a-1 +- New upstream release 3.2.6a +- Add patch fixing CVE-2017-16899 (rhbz#1515695) + +* Tue Nov 07 2017 Adam Jackson - 3.2.6-6 +- Remove unnecessary BuildRequires: imake + +* Thu Aug 03 2017 Fedora Release Engineering - 1:3.2.6-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 1:3.2.6-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Sat Feb 11 2017 Fedora Release Engineering - 1:3.2.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Mon Sep 19 2016 Tomas Repik - 1:3.2.6-2 +- added missing requires for netpbm-progs (RHBZ#1371667) + +* Fri Aug 12 2016 Jozef Mlich - 1:3.2.6-1 +- Resolves #1366524 + rebase to fig2dev 3.2.6 + +* Thu Mar 31 2016 Tomas Repik - 1:3.2.5d-18 +- reading alpha channel of png files properly (#1282615) + +* Fri Feb 05 2016 Fedora Release Engineering - 1:3.2.5d-17 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Fri Jun 19 2015 Fedora Release Engineering - 1:3.2.5d-16 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Mon Aug 18 2014 Fedora Release Engineering - 1:3.2.5d-15 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sun Jun 08 2014 Fedora Release Engineering - 1:3.2.5d-14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue Dec 03 2013 Kamil Dudka - 1:3.2.5d-13 +- make it compile with -Werror=format-security (#1037365) + +* Sun Aug 04 2013 Fedora Release Engineering - 1:3.2.5d-12 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Wed May 15 2013 Kamil Dudka - 1:3.2.5d-11 +- install man pages using the correct file name suffix +- provide the fig2ps2tex.sh man page as a symlink + +* Fri Feb 15 2013 Fedora Release Engineering - 1:3.2.5d-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Tue Aug 28 2012 Kamil Dudka - 1:3.2.5d-9 +- fix specfile issues reported by the fedora-review script + +* Thu Aug 09 2012 Kamil Dudka - 1:3.2.5d-8 +- fix buffer overflow on loading a malformed .fig file (CVE-2009-4227) + +* Sun Jul 22 2012 Fedora Release Engineering - 1:3.2.5d-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Feb 14 2012 Peter Robinson - 1:3.2.5d-6 +- add Gentoo patch to fix compilation with libpng 1.5 + +* Sat Jan 14 2012 Fedora Release Engineering - 1:3.2.5d-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Dec 06 2011 Adam Jackson - 1:3.2.5d-4 +- Rebuild for new libpng + +* Tue Aug 09 2011 Kamil Dudka - 1:3.2.5d-3 +- fix crash of fig2dev on a failure of ghostscript (#728825) + +* Wed Feb 09 2011 Fedora Release Engineering - 1:3.2.5d-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Thu Nov 04 2010 Kamil Dudka - 1:3.2.5d-1 +- new upstream release (#546623) + +* Wed Mar 03 2010 Kamil Dudka - 1:3.2.5c-1 +- new upstream release +- patch to generate comments compliant with DSC 3.0, thanks to Ian Dall + (#558380) + +* Sun Jul 26 2009 Fedora Release Engineering - 1:3.2.5-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue May 5 2009 Ville Skyttä - 1:3.2.5-7 +- Get rid of csh dependency, add missing one on bc (#435993). +- Build with $RPM_OPT_FLAGS (#329831). +- Convert specfile to UTF-8. +- Add URL, fix source URL. +- Escape macros in changelog. +- Improve summary. + +* Wed Feb 25 2009 Fedora Release Engineering - 1:3.2.5-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Sat Dec 20 2008 Ralf Corsépius - 1:3.2.5-5 +- Add transfig-3.2.5-bitmap.patch, tweak permission on sources (BZ #209865). + +* Wed Sep 10 2008 Stepan Kasal - 1:3.2.5-4 +- remove transfig.3.2.4-pstex.patch, which reintroduced #164140 + at the update to 3.2.5 + +* Mon Sep 8 2008 Tom "spot" Callaway - 1:3.2.5-3 +- fix license tag + +* Tue Feb 19 2008 Fedora Release Engineering - 1:3.2.5-2 +- Autorebuild for GCC 4.3 + +* Mon Apr 16 2007 Than Ngo - 1:3.2.5-1.fc7 +- 3.2.5 + +* Wed Aug 16 2006 Stepan Kasal - 1:3.2.4-16 +- Require ghostscript; fig2dev calls it. + +* Wed Jul 12 2006 Jesse Keating - 1:3.2.4-15.1 +- rebuild + +* Tue May 16 2006 Than Ngo 3.2.4-15 +- fix #164140, transfig creates wrong dependencies for -L pstex + +* Tue May 16 2006 Than Ngo 3.2.4-14 +- fix #191825, buildrequire on imake +- fix #173748, fig2dev still refers to /usr/X11R6/lib/X11/rgb.txt + +* Fri Feb 10 2006 Jesse Keating - 1:3.2.4-13.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 1:3.2.4-13.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Mon Dec 19 2005 Than Ngo 3.2.4-13 +- fix build problem with modular X + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Tue Nov 15 2005 Than Ngo 1:3.2.4-12 +- fix for modular X + +* Sat Mar 05 2005 Than Ngo 1:3.2.4-11 +- rebuild + +* Tue Nov 30 2004 Than Ngo 1:3.2.4-10 +- fix compiler warnings #111394 +- fix broken language selection #114849 + +* Tue Nov 30 2004 Than Ngo 1:3.2.4-9 +- add patch to fix getrgb #117099 + +* Mon Oct 18 2004 Miloslav Trmac - 1:3.2.4-8 +- Fix at least a few obvious instances of C abuse (partly #74594 with patch by + Sysoltsev Slawa) +- Drop -Dcfree=free fix, not needed with current version + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Tue Jun 17 2003 Than Ngo 3.2.4-4 +- patch build problem + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Fri May 23 2003 Jeremy Katz 1:3.2.4-2 +- fix build with gcc 3.3 + +* Tue May 6 2003 Than Ngo 3.2.4-1 +- 3.2.4 + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Mon Nov 18 2002 Than Ngo 3.2.3d-8 +- Added a patch file from d.binderman@virgin.net (bug #77980) + +* Wed Jul 31 2002 Than Ngo 3.2.3d-7 +- fig2dev crashes with more than 1 gif files (bug #69917) + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Fri Jun 14 2002 han Ngo 3.2.3d-5 +- fhs fixes (bug #66732) + +* Thu May 23 2002 Tim Powers +- automated rebuild + +* Wed Jan 09 2002 Tim Powers +- automated rebuild + +* Mon Jul 23 2001 Than Ngo +- fix build dependencies (bug #49725) +- Copyright -> License + +* Fri Jun 15 2001 Than Ngo +- update to 3.2.3d release (Bug # 44742) + +* Tue May 29 2001 Than Ngo +- update to 3.2.3d beta2 + +* Fri Apr 13 2001 Than Ngo +- fix core dump when using LDAP auth +- update ftp site + +* Mon Dec 18 2000 Yukihiro Nakai +- Enable Japanese + +* Sat Aug 05 2000 Than Ngo +- update to 3.2.3c (Bug fixed release) + +* Wed Jul 12 2000 Prospector +- automatic rebuild + +* Tue Jun 13 2000 Trond Eivind Glomsrød +- make it build as nobody. Imake sucks. +- include LATEX.AND.XFIG +- use %%{_tmppath} + +* Wed Apr 26 2000 Matt Wilson +- add enable_japanese option, disable it for now. + +* Sun Apr 16 2000 Bryan C. Andregg +- new version to support -b and -g which xfig uses + +* Mon Feb 7 2000 Bill Nottingham +- handle compressed manpages + +* Sun Mar 21 1999 Cristian Gafton +- auto rebuild in the new build environment (release 3) + +* Wed Dec 30 1998 Cristian Gafton +- build for glibc 2.1 + +* Tue Jul 7 1998 Jeff Johnson +- update to 3.2.1. + +* Sat Jun 27 1998 Jeff Johnson +- add %%clean. + +* Mon Apr 27 1998 Prospector System +- translations modified for de, fr, tr + +* Thu Nov 13 1997 Otto Hammersmith +- fixed problem with Imakefile for fig2dev not including $(XLIB) +- build rooted. + +* Fri Oct 24 1997 Otto Hammersmith +- recreated the glibc patch that is needed for an alpha build, missed it + building on the intel. + +* Tue Oct 21 1997 Otto Hammersmith +- updated version +- fixed source url + +* Fri Jul 18 1997 Erik Troan +- built against glibc