Crash when calling gexiv2_metadata_set_tag_multiple with empty list
Describe the bug
In GIMP's metadata-editor we use gexiv2_metadata_set_tag_multiple
to write certain IPTC tags. In certain cases this will cause a crash. See GIMP issue 7408.
To Reproduce
- Make sure that gexiv2 is version 0.14. I self-built current master which at this moment is the same as 0.14.
- Start GIMP development build 2.99.8 (on Windows this uses an older version of gexiv2 which needs to be replaced first)
- Create a new image
- Start the metadata-editor (Image - Metadata - Metadata editor)
- Without entering anything click Write metadata.
- Observe the crash.
Crash log can be seen in GIMP's issue but for completeness I will attach it here too:
Error occurred on Friday, October 22, 2021 at 18:52:58.
metadata-editor.exe caused an Access Violation at location 00007FFA616BD2D0 in module msvcrt.dll Reading from location FFFFFFFFFFFFFFFF.
AddrPC Params
00007FFA616BD2D0 0000000000000080 0000000900000000 000000099E1FF440 msvcrt.dll!strlen
00007FF9FDDC5CB4 0000000000000000 00007FF79D39A6B6 000000099E1FF530 libgexiv2-2.dll!gexiv2_metadata_set_iptc_tag_multiple [D:/msys64/mingw64/include/c++/10.3.0/bits/char_traits.h @ 371]
369: return __gnu_cxx::char_traits<char_type>::length(__s);
370: #endif
> 371: return __builtin_strlen(__s);
372: }
373:
00007FF9FDDB9F5A 000002035C5D8C20 00007FF79D39A6B6 0000000000000000 libgexiv2-2.dll!gexiv2_metadata_try_set_tag_multiple [D:/msys64/home/Jacob/build/gexiv2/../../gexiv2/gexiv2/gexiv2-metadata.cpp @ 1415]
1413:
1414: if (gexiv2_metadata_is_iptc_tag(tag))
> 1415: return gexiv2_metadata_set_iptc_tag_multiple(self, tag, values, error);
1416:
1417: // Invalid "familyName"
00007FF9FDDBA24F 000002035BEBEC20 000002035DB90750 00007FF79D398215 libgexiv2-2.dll!gexiv2_metadata_set_tag_multiple [D:/msys64/home/Jacob/build/gexiv2/../../gexiv2/gexiv2/gexiv2-metadata.cpp @ 1478]
1476: g_return_val_if_fail(self->priv->image.get() != nullptr, FALSE);
1477:
> 1478: success = gexiv2_metadata_try_set_tag_multiple(self, tag, values, &error);
1479:
1480: if (error) {
00007FF79D389613 000002035BEBEBB0 000002035BEBEC20 00000000FFFFFFFA metadata-editor.exe!metadata_editor_write_callback [D:/msys64/home/Jacob/build/gimp/../../gimp/plug-ins/metadata/metadata-editor.c @ 4325]
4323: {
4324: multi = g_strsplit (text, "\n", 0);
> 4325: if (! gexiv2_metadata_set_tag_multiple (GEXIV2_METADATA (g_metadata),
4326: equivalent_metadata_tags[index].tag,
4327: (const gchar **) multi))
00007FF79D38A0AE 00000203596BD2A0 0000000000000002 000000099E1FF970 metadata-editor.exe!metadata_run [D:/msys64/home/Jacob/build/gimp/../../gimp/plug-ins/metadata/metadata-editor.c @ 639]
637: if (run)
638: {
> 639: metadata_editor_write_callback (dialog, builder, image);
640: }
641:
00007FF9F52B037D 000002035966E170 00007FF79D381D16 00007FF900000000 libgimp-3.0-0.dll!gimp_procedure_run [D:/msys64/home/Jacob/build/gimp/../../gimp/libgimp/gimpprocedure.c @ 1905]
1903: {
1904: /* call the procedure */
> 1905: return_vals = GIMP_PROCEDURE_GET_CLASS (procedure)->run (procedure,
1906: args);
1907: }
00007FF9F52AB3F1 00000203596C62E0 0000000000000000 000000099E1FFC50 libgimp-3.0-0.dll!gimp_plug_in_proc_run_internal [D:/msys64/home/Jacob/build/gimp/../../gimp/libgimp/gimpplugin.c @ 1227]
1225: FALSE);
1226:
> 1227: return_values = gimp_procedure_run (procedure, arguments);
1228:
1229: gimp_value_array_unref (arguments);
00007FF9F52ACAE6 000000099E1FFC50 00000203596C8E00 0000020359681FF0 libgimp-3.0-0.dll!_gimp_plug_in_run [D:/msys64/home/Jacob/build/gimp/../../gimp/libgimp/gimpplugin.c @ 1174]
1172: if (procedure)
1173: {
> 1174: gimp_plug_in_proc_run_internal (plug_in,
1175: proc_run, procedure,
1176: &proc_return);
00007FF9F52A2018 00000203596756B0 0000000000000002 00007FF79D4200F8 libgimp-3.0-0.dll!gimp_main [D:/msys64/home/Jacob/build/gimp/../../gimp/libgimp/gimp.c @ 539]
537: g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Here I am!");
538:
> 539: _gimp_plug_in_run (PLUG_IN);
540:
541: gimp_close ();
The problem is both in gexiv2 and in GIMP.
GIMP calls gexiv2_metadata_set_tag_multiple
with an empty list for the last parameter for a tag that doesn't allow multiple values.
Gexiv2 in case of a single tag uses the last value in the list. It iterates the list until nullptr is found and then goes back to the previous one without checking if there was a previous one.
See here.
Expected behaviour
No crash in gexiv2 even with an empty list of values, but instead a return value FALSE to indicate that setting tag failed.
Edit:
Or possibly return TRUE since I think other calls also allow empty values without failing.
Desktop (please complete the following information):
- OS: Windows 10 Home, 64 bits. Installed GIMP 2.99.8 but also self-built GIMP master using MSYS2/MINGW.
- Compiler & version: 10.3.0 (Rev8, Built by MSYS2 project)
- Non-default options: -
Additional context
Add any other context about the problem here.