]> git.eshelyaron.com Git - emacs.git/commitdiff
Prefer make_formatted_string in svg_load_image
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 27 Jan 2025 06:15:49 +0000 (22:15 -0800)
committerEshel Yaron <me@eshelyaron.com>
Thu, 30 Jan 2025 18:06:26 +0000 (19:06 +0100)
* 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.

(cherry picked from commit c50e8c24247eb69d85b004a72197e710c8e1e32a)

src/image.c

index 901063c9bde0f896c661d618e7b3784782a1928c..0d7e77164b616fed326ca5ede61a8ee37ff160b1 100644 (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;
 }