Prefer make_formatted_string in svg_load_image

* src/image.c (svg_load_image): Prefer make_formatted_string to
snprintf, as this simplifies the code and does not truncate the
resulting string arbitrarily.
This commit is contained in:
Paul Eggert 2025-01-26 22:15:49 -08:00
parent 028fae9661
commit c50e8c2424

View file

@ -12048,17 +12048,11 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
int height;
const guint8 *pixels;
int rowstride;
char *wrapped_contents = NULL;
ptrdiff_t wrapped_size;
Lisp_Object wrapped_contents;
bool empty_errmsg = true;
const char *errmsg = "";
ptrdiff_t errlen = 0;
#if LIBRSVG_CHECK_VERSION (2, 48, 0)
char *css = NULL;
#endif
#if ! GLIB_CHECK_VERSION (2, 36, 0)
/* g_type_init is a glib function that must be called prior to
using gnome type library functions (obsolete since 2.36.0). */
@ -12096,23 +12090,11 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
SVG supports, however it's only available in librsvg 2.48 and
above so some things we could set here are handled in the
wrapper below. */
/* FIXME: The below calculations leave enough space for a font
size up to 9999, if it overflows we just throw an error but
should probably increase the buffer size. */
const char *css_spec = "svg{font-family:\"%s\";font-size:%dpx}";
int css_len = strlen (css_spec) + strlen (img->face_font_family) + 1;
css = xmalloc (css_len);
if (css_len <= snprintf (css, css_len, css_spec,
img->face_font_family, img->face_font_size))
goto rsvg_error;
rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *)css, strlen (css), NULL);
}
else
{
css = xmalloc (SBYTES (lcss) + 1);
strncpy (css, SSDATA (lcss), SBYTES (lcss));
*(css + SBYTES (lcss) + 1) = 0;
lcss = make_formatted_string ("svg{font-family:\"%s\";font-size:%dpx}",
img->face_font_family,
img->face_font_size);
rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *) SDATA (lcss),
SBYTES (lcss), NULL);
}
#endif
@ -12280,7 +12262,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
background color, before including the original image. This
acts to set the background color, instead of leaving it
transparent. */
const char *wrapper =
static char const wrapper[] =
"<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
"xmlns:xi=\"http://www.w3.org/2001/XInclude\" "
"style=\"color: #%06X; fill: currentColor;\" "
@ -12290,10 +12272,6 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
"<xi:include href=\"data:image/svg+xml;base64,%s\"></xi:include>"
"</svg>";
/* FIXME: I've added 64 in the hope it will cover the size of the
width and height strings and things. */
int buffer_size = SBYTES (encoded_contents) + strlen (wrapper) + 64;
value = image_spec_value (img->spec, QCforeground, NULL);
if (!NILP (value))
foreground = image_alloc_image_color (f, img, value, img->face_foreground);
@ -12317,22 +12295,18 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
| (background & 0x00FF00);
#endif
wrapped_contents = xmalloc (buffer_size);
if (buffer_size <= snprintf (wrapped_contents, buffer_size, wrapper,
foreground & 0xFFFFFF, width, height,
viewbox_width, viewbox_height,
background & 0xFFFFFF,
SSDATA (encoded_contents)))
goto rsvg_error;
wrapped_size = strlen (wrapped_contents);
unsigned int color = foreground & 0xFFFFFF, fill = background & 0xFFFFFF;
wrapped_contents
= make_formatted_string (wrapper, color, width, height,
viewbox_width, viewbox_height,
fill, SSDATA (encoded_contents));
}
/* Now we parse the wrapped version. */
#if LIBRSVG_CHECK_VERSION (2, 32, 0)
input_stream = g_memory_input_stream_new_from_data (wrapped_contents, wrapped_size, NULL);
input_stream = g_memory_input_stream_new_from_data
(SDATA (wrapped_contents), SBYTES (wrapped_contents), NULL);
base_file = filename ? g_file_new_for_path (filename) : NULL;
rsvg_handle = rsvg_handle_new_from_stream_sync (input_stream, base_file,
RSVG_HANDLE_FLAGS_NONE,
@ -12351,7 +12325,8 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
#if LIBRSVG_CHECK_VERSION (2, 48, 0)
/* Set the CSS for the wrapped SVG. See the comment above the
previous use of 'css'. */
rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *)css, strlen (css), NULL);
rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *) SDATA (lcss),
SBYTES (lcss), NULL);
#endif
#else
/* Make a handle to a new rsvg object. */
@ -12369,7 +12344,8 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
rsvg_handle_set_base_uri (rsvg_handle, filename);
/* Parse the contents argument and fill in the rsvg_handle. */
rsvg_handle_write (rsvg_handle, (unsigned char *) wrapped_contents, wrapped_size, &err);
rsvg_handle_write (rsvg_handle, SDATA (wrapped_contents),
SBYTES (wrapped_contents), &err);
if (err) goto rsvg_error;
/* The parsing is complete, rsvg_handle is ready to used, close it
@ -12389,12 +12365,6 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
if (!pixbuf) goto rsvg_error;
#endif
g_object_unref (rsvg_handle);
xfree (wrapped_contents);
#if LIBRSVG_CHECK_VERSION (2, 48, 0)
if (!STRINGP (lcss))
xfree (css);
#endif
/* Extract some meta data from the svg handle. */
width = gdk_pixbuf_get_width (pixbuf);
@ -12485,12 +12455,6 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
done_error:
if (rsvg_handle)
g_object_unref (rsvg_handle);
if (wrapped_contents)
xfree (wrapped_contents);
#if LIBRSVG_CHECK_VERSION (2, 48, 0)
if (css && !STRINGP (lcss))
xfree (css);
#endif
return false;
}