Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian....@packages.debian.org
Usertags: pu

While 3.2.7a-5+deb10u2 is currently in proposed-updates I prepared
another update (deb10u3) fixing CVE-2019-19746 and CVE-2019-19797 as
well as 6 further segfaults, which are only in upstream tracker and
don't have a CVE:
https://sourceforge.net/p/mcj/tickets/58
https://sourceforge.net/p/mcj/tickets/59
https://sourceforge.net/p/mcj/tickets/61
https://sourceforge.net/p/mcj/tickets/62
https://sourceforge.net/p/mcj/tickets/78
https://sourceforge.net/p/mcj/tickets/79

According to security-tracker CVE-2019-19746 is "unimportant" and
CVE-2019-19797 is tagged "no DSA", so I didn't send this to the
security team, but request a point release update.

Hopefully the second patch isn't too big for a point release, but
since upstream fixed several segfaults with this, it won't be a good
idea to extract only parts from it to fix only CVE-2019-19797 but keep
the root cause of all these segfaults...

Attached you'll find a patch agains 3.2.7a-5+deb10u2.

Greetings
Roland
diff -Nru fig2dev-3.2.7a/debian/changelog fig2dev-3.2.7a/debian/changelog
--- fig2dev-3.2.7a/debian/changelog	2019-12-04 22:12:49.000000000 +0100
+++ fig2dev-3.2.7a/debian/changelog	2020-01-07 19:53:09.000000000 +0100
@@ -1,3 +1,13 @@
+fig2dev (1:3.2.7a-5+deb10u3) buster; urgency=medium
+
+  * 42_CVE-2019-19746: Reject huge arrow types causing integer overflow.
+    This fixes CVE-2019-19746 (Closes: #946628).
+  * 43_fgets2getline: Replace most calls to fgets() by getline() in
+     read.c.  This fixes CVE-2019-19797 and several other segfaults
+    (Closes: #946866).
+
+ -- Roland Rosenfeld <rol...@debian.org>  Tue, 07 Jan 2020 19:53:09 +0100
+
 fig2dev (1:3.2.7a-5+deb10u2) buster; urgency=medium
 
   * 41_CVE-2019-19555: Allow Fig v2 text strings ending with multiple ^A.
diff -Nru fig2dev-3.2.7a/debian/patches/42_CVE-2019-19746.patch fig2dev-3.2.7a/debian/patches/42_CVE-2019-19746.patch
--- fig2dev-3.2.7a/debian/patches/42_CVE-2019-19746.patch	1970-01-01 01:00:00.000000000 +0100
+++ fig2dev-3.2.7a/debian/patches/42_CVE-2019-19746.patch	2020-01-07 19:53:09.000000000 +0100
@@ -0,0 +1,44 @@
+From: Thomas Loimer <thomas.loi...@tuwien.ac.at>
+Date: Tue Dec 10 13:17:36 2019 +0100
+Bug: https://sourceforge.net/p/mcj/tickets/57
+Bug-Debian: https://bugs.debian.org/946628
+Origin: https://sourceforge.net/p/mcj/fig2dev/ci/3065abc7b4f740ed6532322843531317de782a26/
+Subject: Reject huge arrow types causing integer overflow.
+ This fixes CVE-2019-19746
+
+--- 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 t
+ {
+ 	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 t
+ 
+ 	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 -Nru fig2dev-3.2.7a/debian/patches/43_fgets2getline.patch fig2dev-3.2.7a/debian/patches/43_fgets2getline.patch
--- fig2dev-3.2.7a/debian/patches/43_fgets2getline.patch	1970-01-01 01:00:00.000000000 +0100
+++ fig2dev-3.2.7a/debian/patches/43_fgets2getline.patch	2020-01-07 19:53:09.000000000 +0100
@@ -0,0 +1,1717 @@
+From: Thomas Loimer <thomas.loi...@tuwien.ac.at>
+Date: Sun Jan 5 19:22:12 2020 +0100
+Bug: https://sourceforge.net/p/mcj/tickets/58
+Bug: https://sourceforge.net/p/mcj/tickets/59
+Bug: https://sourceforge.net/p/mcj/tickets/61
+Bug: https://sourceforge.net/p/mcj/tickets/62
+Bug: https://sourceforge.net/p/mcj/tickets/67
+Bug: https://sourceforge.net/p/mcj/tickets/78
+Bug: https://sourceforge.net/p/mcj/tickets/79
+Bug-Debian: https://bugs.debian.org/946866
+Origin: https://sourceforge.net/p/mcj/fig2dev/ci/41b9bb838a3d544539f6e68aa4f87d70ef7d45ce/
+Subject: 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.
+
+ This fixes CVE-2019-19797
+
+--- a/fig2dev/fig2dev.c
++++ b/fig2dev/fig2dev.c
+@@ -81,7 +81,7 @@ bool	bgspec = false;		/* flag to say -g
+ 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) */
+--- a/fig2dev/fig2dev.h
++++ b/fig2dev/fig2dev.h
+@@ -95,7 +95,7 @@ extern bool	bgspec;		/* flag to say -g w
+ 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 char	*Fig_color_names[]; /* hex names for Fig colors */
+--- 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
+ 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 ar
+ /* 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<num_usr_cols; ++i)
++	    /* read_colordef() counted, but ignored too many user colors */
++	    if (num_usr_cols > 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;
++	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;
++	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<num_usr_cols; ++i)
+-	if (*color == user_col_indx[i]) {
+-		*color = i + NUM_STD_COLS;
++	if (*color < NUM_STD_COLS) {
++		if (*color >= 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 (INVALID_ELLIPSE(e)) {
+@@ -781,7 +862,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;
+ }
+@@ -798,8 +879,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;
+@@ -886,7 +968,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;
+@@ -907,40 +989,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;
+ 	}
+@@ -948,45 +1028,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);
+@@ -1000,21 +1082,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;
+@@ -1023,8 +1106,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);
+ 	    }
+ 	}
+ 
+@@ -1036,9 +1119,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;
+ 	}
+@@ -1046,9 +1129,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;
+ 	    }
+@@ -1077,7 +1160,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;
+ 	}
+@@ -1089,7 +1172,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;
+@@ -1111,58 +1195,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;
+ 	    }
+@@ -1170,9 +1254,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;
+ 	    };
+@@ -1186,15 +1270,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;
+ 		};
+@@ -1224,9 +1308,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;
+ 		}
+@@ -1249,9 +1333,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;
+ 	}
+@@ -1264,9 +1348,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;
+@@ -1289,13 +1373,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;
+@@ -1303,32 +1411,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(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);
++	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);
++
++	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);
+-	}
+-	if ((n != 14) && (n != 13)) {
+-	  put_msg(Err_incomp, "text", line_no);
+-	  free(t);
+-	  return NULL;
++		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 */
++	}
++
++	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 */
+@@ -1338,89 +1515,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)
+@@ -1431,11 +1525,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;
+ }
+@@ -1443,18 +1537,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 */
+@@ -1483,55 +1578,64 @@ 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;
+-		}
+-		++line_no;
+-		if (*buf == '#') {			/* save any comments */
+-			if (save_comment() < 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;
+-		}
+-	}
+-}
++	int	i;
+ 
+-/* save a comment line to be stored with the *subsequent* object */
++	/* 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;
+ 
+-static int
+-save_comment(void)
++	strcpy(comments[numcom++], &line[i]);
++	return 1;
++}
++
++static ssize_t
++get_line(FILE *fp, char **restrict line, size_t *line_len, int *line_no)
+ {
+-    int		    i;
++	ssize_t	chars;
+ 
+-    /* 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;
++	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';
++		}
++		/* save any comments */
++		if (**line == '#') {
++			if (save_comment(*line, (size_t)chars) < 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. */
+ }
+ 
++
+ /* skip to the end of the current line and any subsequent blank lines */
+ 
+ static void
+@@ -1688,15 +1792,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);
+ }
+--- a/fig2dev/read1_3.c
++++ b/fig2dev/read1_3.c
+@@ -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 *o
+ 			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 *o
+ 			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 *o
+ 			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 *o
+ 			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 *o
+ 			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 *o
+ 			lc = (lc->next = c);
+ 		    else
+ 			lc = obj->compounds = c;
+-		    num_object++;
+ 		    break;
+ 		default:
+ 		    put_msg("Incorrect object code %d", object);
diff -Nru fig2dev-3.2.7a/debian/patches/series fig2dev-3.2.7a/debian/patches/series
--- fig2dev-3.2.7a/debian/patches/series	2019-12-04 22:12:49.000000000 +0100
+++ fig2dev-3.2.7a/debian/patches/series	2020-01-07 19:53:09.000000000 +0100
@@ -13,3 +13,5 @@
 38_omit_showpage.patch
 40_circle_arrowhead.patch
 41_CVE-2019-19555.patch
+42_CVE-2019-19746.patch
+43_fgets2getline.patch

Attachment: signature.asc
Description: PGP signature

Reply via email to