From a23b4732e322076f931be57bbd4cf4a2b84940f9 Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Fri, 26 Jul 2024 14:58:36 +0200 Subject: [PATCH] Distinguish EOF and empty lines when parsing text pal files --- src/gfx/pal_spec.cpp | 34 +++++++++++++++++++++------------- test/gfx/truncated_gpl.err | 2 ++ test/gfx/truncated_gpl.flags | 1 + test/gfx/truncated_gpl.gpl | 1 + test/gfx/truncated_gpl.png | Bin 0 -> 712 bytes 5 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 test/gfx/truncated_gpl.err create mode 100644 test/gfx/truncated_gpl.flags create mode 100644 test/gfx/truncated_gpl.gpl create mode 100644 test/gfx/truncated_gpl.png diff --git a/src/gfx/pal_spec.cpp b/src/gfx/pal_spec.cpp index 9007d35c..35b65af8 100644 --- a/src/gfx/pal_spec.cpp +++ b/src/gfx/pal_spec.cpp @@ -176,6 +176,7 @@ void parseInlinePalSpec(char const * const rawArg) { * Returns whether the magic was correctly read. */ template +[[gnu::warn_unused_result]] // Ignoring failure to match is a bad idea. static bool readMagic(std::filebuf &file, char const *magic) { assume(strlen(magic) == n); @@ -203,26 +204,36 @@ static T readLE(U const *bytes) { /* * **Appends** the first line read from `file` to the end of the provided `buffer`. + * + * @return true if a line was read. */ -static void readLine(std::filebuf &file, std::string &buffer) { +[[gnu::warn_unused_result]] // Ignoring EOF is a bad idea. +static bool readLine(std::filebuf &file, std::string &buffer) { // TODO: maybe this can be optimized to bulk reads? for (;;) { auto c = file.sbumpc(); if (c == std::filebuf::traits_type::eof()) { - return; + return false; } if (c == '\n') { // Discard a trailing CRLF if (!buffer.empty() && buffer.back() == '\r') { buffer.pop_back(); } - return; + return true; } buffer.push_back(c); } } +#define requireLine(kind, file, buffer) do { \ + if (!readLine(file, buffer)) { \ + error(kind " palette file is shorter than expected"); \ + return; \ + } \ +} while (0) + /* * Parses the initial part of a string_view, advancing the "read index" as it does */ @@ -272,21 +283,20 @@ static void parsePSPFile(std::filebuf &file) { // https://www.selapa.net/swatches/colors/fileformats.php#psp_pal std::string line; - readLine(file, line); - if (line != "JASC-PAL") { + if (!readLine(file, line) || line != "JASC-PAL") { error("Palette file does not appear to be a PSP palette file"); return; } line.clear(); - readLine(file, line); + requireLine("PSP", file, line); if (line != "0100") { error("Unsupported PSP palette file version \"%s\"", line.c_str()); return; } line.clear(); - readLine(file, line); + requireLine("PSP", file, line); std::string::size_type n = 0; std::optional nbColors = parseDec(line, n); if (!nbColors || n != line.length()) { @@ -309,7 +319,7 @@ static void parsePSPFile(std::filebuf &file) { for (uint16_t i = 0; i < *nbColors; ++i) { line.clear(); - readLine(file, line); + requireLine("PSP", file, line); n = 0; std::optional color = parseColor(line, n, i + 1); @@ -336,8 +346,7 @@ static void parseGPLFile(std::filebuf &file) { // https://gitlab.gnome.org/GNOME/gimp/-/blob/gimp-2-10/app/core/gimppalette-load.c#L39 std::string line; - readLine(file, line); - if (!line.starts_with("GIMP Palette")) { + if (!readLine(file, line) || !line.starts_with("GIMP Palette")) { error("Palette file does not appear to be a GPL palette file"); return; } @@ -347,7 +356,7 @@ static void parseGPLFile(std::filebuf &file) { for (;;) { line.clear(); - readLine(file, line); + requireLine("GPL", file, line); if (!line.length()) { break; } @@ -389,8 +398,7 @@ static void parseHEXFile(std::filebuf &file) { for (;;) { std::string line; - readLine(file, line); - if (!line.length()) { + if (!readLine(file, line)) { break; } diff --git a/test/gfx/truncated_gpl.err b/test/gfx/truncated_gpl.err new file mode 100644 index 00000000..1ee64920 --- /dev/null +++ b/test/gfx/truncated_gpl.err @@ -0,0 +1,2 @@ +error: GPL palette file appears to be truncated +Conversion aborted after 1 error diff --git a/test/gfx/truncated_gpl.flags b/test/gfx/truncated_gpl.flags new file mode 100644 index 00000000..102b83ef --- /dev/null +++ b/test/gfx/truncated_gpl.flags @@ -0,0 +1 @@ +-c gpl:truncated_gpl.gpl diff --git a/test/gfx/truncated_gpl.gpl b/test/gfx/truncated_gpl.gpl new file mode 100644 index 00000000..ab477b6a --- /dev/null +++ b/test/gfx/truncated_gpl.gpl @@ -0,0 +1 @@ +GIMP Palette diff --git a/test/gfx/truncated_gpl.png b/test/gfx/truncated_gpl.png new file mode 100644 index 0000000000000000000000000000000000000000..57fdd36f50ceea06ff1b3c6d58a745fd05c30f13 GIT binary patch literal 712 zcmV;(0yq7MP)EX>4Tx04R}tkv&MmKp2MKrk09SMA|{bAwzYtAS&XhRVYG*P%E_RU~=gnG%+M8 zE{=k0!NH%!s)LKOt`4q(Aov5~=;Wm6A|-y86k5c1$8itueecWNcYx5SGR^8512o+> zGpVGQ%dd#xSA-BnKh3zzEMr!Z((oN$_XzO)F2S?>>;4?QYQbVaKqQ`FhG`S86Hjg0 z2Iqa^7%R&v@j3CRNf#u3)BVfh)c3-)I2SpQP8@ zTKov;+XgPK+nTZmT zjFc#Q&F9_SoqhYarq#b6S`%`eYNz2J00009a7bBm001r{001r{0eGc9b^rhX>PbXF zR7l6oRxu94APfX6FR7F+eM^=MRi9XOV98s$G*Z7phDeo*iERvt;w{0tGv_nlV~p-U zUhnkJR@`r1%mFjHG8tT5h#X)pUm4(bjs^t$zPoyYFw6mcKEGGI>ak6gJqW|hCtwaJ z^|gq8w2QhTt*czbmv2MgWeyS-L0fSWbQOUfeVlr#b2Ev?skijN+}jKRow9oL!%tJZ zi6-S|cCd1^LeER2Ir2__qtSun&CZ0U?;;$J%O{JTGzl*y3JU~34rT4Me=