Skip to content

Commit 8a9baf0

Browse files
authored
Merge pull request #53 from agruzdev/xbm-regex
PluginXBM: use regex in Load() as standard-compliant and safe text parser
2 parents 16c4020 + a187195 commit 8a9baf0

1 file changed

Lines changed: 54 additions & 47 deletions

File tree

Source/Plugins/PluginXBM.cpp

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@
2929
// Internal functions
3030
// ==========================================================
3131

32-
#define MAX_LINE 512
32+
#define MAX_LINE 512
33+
#define LINE_FORMAT_WIDTH_OR_HEIGHT "#define %" FI_QUOTE(MAX_LINE) "s %d"
34+
#define LINE_FORMAT_BITS_V10 "static short %" FI_QUOTE(MAX_LINE) "s = {"
35+
#define LINE_FORMAT_BITS_V11_OPT1 "static char %" FI_QUOTE(MAX_LINE) "s = {"
36+
#define LINE_FORMAT_BITS_V11_OPT2 "static unsigned char %" FI_QUOTE(MAX_LINE) "s = {"
3337

3438
static const char *ERR_XBM_SYNTAX = "Syntax error";
3539
static const char *ERR_XBM_LINE = "Line too long";
@@ -87,76 +91,79 @@ Read an XBM file into a buffer
8791
*/
8892
static const char*
8993
readXBMFile(FreeImageIO *io, fi_handle handle, int *widthP, int *heightP, std::unique_ptr<void, decltype(&free)> &dataP) {
90-
char line[MAX_LINE], name_and_type[MAX_LINE];
91-
char *ptr{};
92-
char *t{};
94+
std::string line(MAX_LINE, '\0'), name(MAX_LINE + 1, '\0');
95+
char *ptr{};
9396
int version = 0;
9497
size_t bytes, bytes_per_line, raster_length;
95-
int v, padding;
9698
int c1, c2, value1, value2;
9799
int hex_table[256];
98-
bool found_declaration{}; // haven't found it yet; haven't even looked
100+
bool found_declaration{}; // haven't found it yet; haven't even looked
99101
/* in scanning through the bitmap file, we have found the first
100-
line of the C declaration of the array (the "static char ..."
101-
or whatever line)
102+
line of the C declaration of the array (the "static char ..." or whatever line)
102103
*/
103-
bool eof{}; // we've encountered end of file while searching file
104104

105105
*widthP = *heightP = -1;
106106

107-
while (!found_declaration && !eof) {
107+
for (;;) {
108+
if (!readLine(line.data(), MAX_LINE, io, handle)) {
109+
break;
110+
}
108111

109-
if (!readLine(line, MAX_LINE, io, handle)) {
110-
eof = true;
112+
if (strlen(line.c_str()) >= MAX_LINE - 1) {
113+
return ERR_XBM_LINE;
111114
}
112-
else {
113-
if (strlen(line) == MAX_LINE - 1)
114-
return( ERR_XBM_LINE );
115-
if (sscanf_s(line, "#define %s %d", name_and_type, MAX_LINE, &v) == 2) {
116-
if ((t = strrchr(name_and_type, '_')) == nullptr)
117-
t = name_and_type;
118-
else
119-
t++;
120-
if (!strcmp("width", t))
121-
*widthP = v;
122-
else if (!strcmp("height", t))
123-
*heightP = v;
124-
continue;
125-
}
126115

127-
if (sscanf_s(line, "static short %s = {", name_and_type, MAX_LINE) == 1) {
128-
version = 10;
129-
found_declaration = true;
130-
}
131-
else if (sscanf_s(line, "static char %s = {", name_and_type, MAX_LINE) == 1) {
132-
version = 11;
133-
found_declaration = true;
134-
}
135-
else if (sscanf_s(line, "static unsigned char %s = {", name_and_type, MAX_LINE) == 1) {
136-
version = 11;
137-
found_declaration = true;
116+
int val{};
117+
if (2 == std::sscanf(line.c_str(), LINE_FORMAT_WIDTH_OR_HEIGHT, name.data(), &val)) {
118+
if (const auto suffix = std::strrchr(name.c_str(), '_')) {
119+
if (0 == std::strcmp("_width", suffix)) {
120+
*widthP = val;
121+
continue;
122+
}
123+
if (0 == std::strcmp("_height", suffix)) {
124+
*heightP = val;
125+
continue;
126+
}
138127
}
139128
}
129+
130+
if (1 == std::sscanf(line.c_str(), LINE_FORMAT_BITS_V10, name.data())) {
131+
version = 10;
132+
found_declaration = true;
133+
break;
134+
}
135+
136+
if (1 == std::sscanf(line.c_str(), LINE_FORMAT_BITS_V11_OPT1, name.data()) ||
137+
1 == std::sscanf(line.c_str(), LINE_FORMAT_BITS_V11_OPT2, name.data())) {
138+
version = 11;
139+
found_declaration = true;
140+
break;
141+
}
140142
}
141143

142-
if (!found_declaration)
143-
return( ERR_XBM_DECL );
144+
if (!found_declaration) {
145+
return ERR_XBM_DECL;
146+
}
144147

145-
if (*widthP == -1)
146-
return( ERR_XBM_WIDTH );
147-
if (*heightP == -1)
148-
return( ERR_XBM_HEIGHT );
148+
if (*widthP <= 0) {
149+
return ERR_XBM_WIDTH;
150+
}
151+
if (*heightP <= 0) {
152+
return ERR_XBM_HEIGHT;
153+
}
149154

150-
padding = 0;
151-
if ( ((*widthP % 16) >= 1) && ((*widthP % 16) <= 8) && (version == 10) )
155+
int padding = 0;
156+
if (((*widthP % 16) >= 1) && ((*widthP % 16) <= 8) && (version == 10)) {
152157
padding = 1;
158+
}
153159

154160
bytes_per_line = (*widthP + 7) / 8 + padding;
155161

156162
raster_length = bytes_per_line * *heightP;
157163
dataP.reset(malloc(raster_length));
158-
if (!dataP)
159-
return( ERR_XBM_MEMORY );
164+
if (!dataP) {
165+
return ERR_XBM_MEMORY;
166+
}
160167

161168
// initialize hex_table
162169
for ( c1 = 0; c1 < 256; c1++ ) {

0 commit comments

Comments
 (0)