Skip to content

Commit 86ed684

Browse files
committed
avcodec/librsvgdec: fix memory leaks and deprecated functions
At various points through the function librsvg_decode_frame, errors are returned from immediately without deallocating any allocated structs. This patch both fixes those leaks, and also fixes the use of functions that are deprecated since librsvg version 2.52.0. The older calls are still used, guarded by #ifdefs while the newer replacements are used if librsvg >= 2.52.0. One of the deprecated functions is used as a check for the configure shell script, so it was replaced with a different function. Signed-off-by: Leo Izen <[email protected]>
1 parent a76b409 commit 86ed684

File tree

2 files changed

+63
-20
lines changed

2 files changed

+63
-20
lines changed

configure

+1-1
Original file line numberDiff line numberDiff line change
@@ -6786,7 +6786,7 @@ enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaud
67866786
enabled librabbitmq && require_pkg_config librabbitmq "librabbitmq >= 0.7.1" amqp.h amqp_new_connection
67876787
enabled librav1e && require_pkg_config librav1e "rav1e >= 0.5.0" rav1e.h rav1e_context_new
67886788
enabled librist && require_pkg_config librist "librist >= 0.2.7" librist/librist.h rist_receiver_create
6789-
enabled librsvg && require_pkg_config librsvg librsvg-2.0 librsvg-2.0/librsvg/rsvg.h rsvg_handle_render_cairo
6789+
enabled librsvg && require_pkg_config librsvg librsvg-2.0 librsvg-2.0/librsvg/rsvg.h rsvg_handle_new_from_data
67906790
enabled librtmp && require_pkg_config librtmp librtmp librtmp/rtmp.h RTMP_Socket
67916791
enabled librubberband && require_pkg_config librubberband "rubberband >= 1.8.1" rubberband/rubberband-c.h rubberband_new -lstdc++ && append librubberband_extralibs "-lstdc++"
67926792
enabled libshaderc && require_pkg_config spirv_compiler "shaderc >= 2019.1" shaderc/shaderc.h shaderc_compiler_initialize

libavcodec/librsvgdec.c

+62-19
Original file line numberDiff line numberDiff line change
@@ -38,48 +38,75 @@ static int librsvg_decode_frame(AVCodecContext *avctx, AVFrame *frame,
3838
{
3939
int ret;
4040
LibRSVGContext *s = avctx->priv_data;
41-
42-
RsvgHandle *handle;
43-
RsvgDimensionData unscaled_dimensions, dimensions;
44-
cairo_surface_t *image;
41+
RsvgHandle *handle = NULL;
42+
RsvgDimensionData dimensions;
43+
#if LIBRSVG_MAJOR_VERSION > 2 || LIBRSVG_MAJOR_VERSION == 2 && LIBRSVG_MINOR_VERSION >= 52
44+
RsvgRectangle viewport = { 0 };
45+
#else
46+
RsvgDimensionData unscaled_dimensions;
47+
#endif
48+
cairo_surface_t *image = NULL;
4549
cairo_t *crender = NULL;
4650
GError *error = NULL;
51+
gboolean gret;
4752

4853
*got_frame = 0;
4954

5055
handle = rsvg_handle_new_from_data(pkt->data, pkt->size, &error);
5156
if (error) {
52-
av_log(avctx, AV_LOG_ERROR, "Error parsing svg!\n");
53-
g_error_free(error);
54-
return AVERROR_INVALIDDATA;
57+
av_log(avctx, AV_LOG_ERROR, "Error parsing svg: %s\n", error->message);
58+
ret = AVERROR_INVALIDDATA;
59+
goto end;
5560
}
5661

62+
#if LIBRSVG_MAJOR_VERSION > 2 || LIBRSVG_MAJOR_VERSION == 2 && LIBRSVG_MINOR_VERSION >= 52
63+
gret = rsvg_handle_get_intrinsic_size_in_pixels(handle, &viewport.width, &viewport.height);
64+
if (!gret) {
65+
viewport.width = s->width ? s->width : 100;
66+
viewport.height = s->height ? s->height : 100;
67+
}
68+
dimensions.width = (int)viewport.width;
69+
dimensions.height = (int)viewport.height;
70+
#else
5771
rsvg_handle_get_dimensions(handle, &dimensions);
5872
rsvg_handle_get_dimensions(handle, &unscaled_dimensions);
73+
#endif
5974
dimensions.width = s->width ? s->width : dimensions.width;
6075
dimensions.height = s->height ? s->height : dimensions.height;
6176
if (s->keep_ar && (s->width || s->height)) {
77+
#if LIBRSVG_MAJOR_VERSION > 2 || LIBRSVG_MAJOR_VERSION == 2 && LIBRSVG_MINOR_VERSION >= 52
78+
double default_ar = viewport.width / viewport.height;
79+
#else
6280
double default_ar = unscaled_dimensions.width/(double)unscaled_dimensions.height;
81+
#endif
6382
if (!s->width)
6483
dimensions.width = lrintf(dimensions.height * default_ar);
6584
else
6685
dimensions.height = lrintf(dimensions.width / default_ar);
6786
}
6887

69-
if ((ret = ff_set_dimensions(avctx, dimensions.width, dimensions.height)))
70-
return ret;
88+
ret = ff_set_dimensions(avctx, dimensions.width, dimensions.height);
89+
if (ret < 0)
90+
goto end;
91+
7192
avctx->pix_fmt = AV_PIX_FMT_RGB32;
93+
viewport.width = dimensions.width;
94+
viewport.height = dimensions.height;
95+
96+
ret = ff_get_buffer(avctx, frame, 0);
97+
if (ret < 0)
98+
goto end;
7299

73-
if ((ret = ff_get_buffer(avctx, frame, 0)))
74-
return ret;
75100
frame->pict_type = AV_PICTURE_TYPE_I;
76101
frame->flags |= AV_FRAME_FLAG_KEY;
77102

78103
image = cairo_image_surface_create_for_data(frame->data[0], CAIRO_FORMAT_ARGB32,
79104
frame->width, frame->height,
80105
frame->linesize[0]);
81-
if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS)
82-
return AVERROR_INVALIDDATA;
106+
if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) {
107+
ret = AVERROR_EXTERNAL;
108+
goto end;
109+
}
83110

84111
crender = cairo_create(image);
85112

@@ -88,18 +115,34 @@ static int librsvg_decode_frame(AVCodecContext *avctx, AVFrame *frame,
88115
cairo_paint(crender);
89116
cairo_restore(crender);
90117

118+
#if LIBRSVG_MAJOR_VERSION > 2 || LIBRSVG_MAJOR_VERSION == 2 && LIBRSVG_MINOR_VERSION >= 52
119+
gret = rsvg_handle_render_document(handle, crender, &viewport, &error);
120+
#else
91121
cairo_scale(crender, dimensions.width / (double)unscaled_dimensions.width,
92122
dimensions.height / (double)unscaled_dimensions.height);
123+
gret = rsvg_handle_render_cairo(handle, crender);
124+
#endif
93125

94-
rsvg_handle_render_cairo(handle, crender);
95-
96-
cairo_destroy(crender);
97-
cairo_surface_destroy(image);
98-
g_object_unref(handle);
126+
if (!gret) {
127+
av_log(avctx, AV_LOG_ERROR, "Error rendering svg: %s\n", error ? error->message : "unknown error");
128+
ret = AVERROR_EXTERNAL;
129+
goto end;
130+
}
99131

100132
*got_frame = 1;
133+
ret = 0;
101134

102-
return 0;
135+
end:
136+
if (error)
137+
g_error_free(error);
138+
if (handle)
139+
g_object_unref(handle);
140+
if (crender)
141+
cairo_destroy(crender);
142+
if (image)
143+
cairo_surface_destroy(image);
144+
145+
return ret;
103146
}
104147

105148
#define OFFSET(x) offsetof(LibRSVGContext, x)

0 commit comments

Comments
 (0)