summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Roche <xroche@users.noreply.github.com>2014-05-28 18:31:40 +0000
committerXavier Roche <xroche@users.noreply.github.com>2014-05-28 18:31:40 +0000
commit27752e368cc8e6325894d3a2a31f3faa80cbd93f (patch)
tree4a3e1609b17eef009d256926a8793e17237d16ae
parent37187f967fb2a2c7257fdc1965c16381ffed4a2c (diff)
Rewrite template formatting to be format-injection proof.
-rw-r--r--src/htscore.c4
-rw-r--r--src/htsparse.c10
-rw-r--r--src/htstools.c68
-rw-r--r--src/htstools.h1
4 files changed, 69 insertions, 14 deletions
diff --git a/src/htscore.c b/src/htscore.c
index 80efcb9..b1dac1a 100644
--- a/src/htscore.c
+++ b/src/htscore.c
@@ -387,9 +387,9 @@ if (makeindex_fp) { \
sprintf(tempo,"<meta HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=%s\">"CRLF, link_escaped); \
} else \
tempo[0]='\0'; \
- fprintf(makeindex_fp,template_footer, \
+ hts_template_format(makeindex_fp,template_footer, \
"<!-- Mirror and index made by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->", \
- tempo \
+ tempo, /* EOF */ NULL \
); \
fflush(makeindex_fp); \
fclose(makeindex_fp); /* à ne pas oublier sinon on passe une nuit blanche */ \
diff --git a/src/htsparse.c b/src/htsparse.c
index e49b00f..53872b5 100644
--- a/src/htsparse.c
+++ b/src/htsparse.c
@@ -207,9 +207,9 @@ Please visit our Website: http://www.httrack.com
sprintf(tempo,"<meta HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=%s\">"CRLF,link_escaped); \
} else \
tempo[0]='\0'; \
- fprintf(makeindex_fp,template_footer, \
+ hts_template_format(makeindex_fp,template_footer, \
"<!-- Mirror and index made by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->", \
- tempo \
+ tempo, /* EOF */ NULL \
); \
fflush(makeindex_fp); \
fclose(makeindex_fp); /* à ne pas oublier sinon on passe une nuit blanche */ \
@@ -587,9 +587,9 @@ int htsparse(htsmoduleStruct * str, htsmoduleStructExtended * stre) {
if (makeindex_fp != NULL) {
// Header
- fprintf(makeindex_fp, template_header,
+ hts_template_format(makeindex_fp, template_header,
"<!-- Mirror and index made by HTTrack Website Copier/"
- HTTRACK_VERSION " " HTTRACK_AFF_AUTHORS " -->");
+ HTTRACK_VERSION " " HTTRACK_AFF_AUTHORS " -->", /* EOF */ NULL);
} else
makeindex_done = -1; // fait, erreur
@@ -651,7 +651,7 @@ int htsparse(htsmoduleStruct * str, htsmoduleStructExtended * stre) {
// Body
inplace_escape_uri_utf(tempo, sizeof(tempo));
- fprintf(makeindex_fp, template_body, tempo, s);
+ hts_template_format(makeindex_fp, template_body, tempo, s, /* EOF */ NULL);
}
}
}
diff --git a/src/htstools.c b/src/htstools.c
index 65443ad..ae68e60 100644
--- a/src/htstools.c
+++ b/src/htstools.c
@@ -757,7 +757,61 @@ static int sortTopIndexFnc(const void *a_, const void *b_) {
return cmp;
}
-//HTSEXT_API char *hts_getcategory(const char *filename);
+// note: upstream arg list MUST be NULL-terminated for safety
+// returns a negative value upon error
+static int hts_template_formatv(FILE *const fp, const char *format, va_list args) {
+ if (fp != NULL && format != NULL) {
+ const char *arg_expanded[32];
+ size_t i, nbArgs, posArgs;
+ /* Expand internal code args. */
+ const char *str;
+ for(nbArgs = 0 ; ( str = va_arg(args, const char*) ) != NULL ; nbArgs++) {
+ assertf(nbArgs < sizeof(arg_expanded)/sizeof(arg_expanded[0]));
+ arg_expanded[nbArgs] = str;
+ }
+ /* Expand user-injected format string. */
+ for(posArgs = 0, i = 0 ; format[i] != '\0' ; i++) {
+ const unsigned char c = format[i];
+ if (c == '%') {
+ const unsigned char cFormat = format[++i];
+ switch(cFormat) {
+ case '%':
+ fputc('%', fp);
+ break;
+ case 's':
+ if (posArgs < nbArgs) {
+ assertf(arg_expanded[posArgs] != NULL);
+ fputs(arg_expanded[posArgs], fp);
+ posArgs++;
+ } else {
+ fputs("???", fp); /* error (args overflow) */
+ }
+ break;
+ default: /* ignored */
+ fputc('%', fp);
+ fputc(cFormat, fp);
+ break;
+ }
+ } else {
+ fputc(c, fp);
+ }
+ }
+ return 1;
+ } else {
+ return -1;
+ }
+}
+
+// note: upstream arg list MUST be NULL-terminated for safety
+// returns a negative value upon error
+int hts_template_format(FILE *const out, const char *format, ...) {
+ int success;
+ va_list args;
+ va_start(args, format);
+ success = hts_template_formatv(out, format, args);
+ va_end(args);
+ return success;
+}
/* Note: NOT utf-8 */
HTSEXT_API int hts_buildtopindex(httrackp * opt, const char *path,
@@ -798,9 +852,9 @@ HTSEXT_API int hts_buildtopindex(httrackp * opt, const char *path,
verif_backblue(opt, concat(catbuff, sizeof(catbuff), rpath, "/")); // générer gif
// Header
- fprintf(fpo, toptemplate_header,
+ hts_template_format(fpo, toptemplate_header,
"<!-- Mirror and index made by HTTrack Website Copier/"
- HTTRACK_VERSION " " HTTRACK_AFF_AUTHORS " -->");
+ HTTRACK_VERSION " " HTTRACK_AFF_AUTHORS " -->", /* EOF */ NULL);
/* Find valid project names */
h = hts_findfirst(rpath);
@@ -891,9 +945,9 @@ HTSEXT_API int hts_buildtopindex(httrackp * opt, const char *path,
/* Changed category */
if (strcmp(category, sortedElts[i]->category) != 0) {
category = sortedElts[i]->category;
- fprintf(fpo, toptemplate_bodycat, category);
+ hts_template_format(fpo, toptemplate_bodycat, category, /* EOF */ NULL);
}
- fprintf(fpo, toptemplate_body, hname, sortedElts[i]->name);
+ hts_template_format(fpo, toptemplate_body, hname, sortedElts[i]->name, /* EOF */ NULL);
}
/* Wipe elements */
@@ -911,9 +965,9 @@ HTSEXT_API int hts_buildtopindex(httrackp * opt, const char *path,
}
// Footer
- fprintf(fpo, toptemplate_footer,
+ hts_template_format(fpo, toptemplate_footer,
"<!-- Mirror and index made by HTTrack Website Copier/"
- HTTRACK_VERSION " " HTTRACK_AFF_AUTHORS " -->");
+ HTTRACK_VERSION " " HTTRACK_AFF_AUTHORS " -->", /* EOF */ NULL);
fclose(fpo);
diff --git a/src/htstools.h b/src/htstools.h
index 8db206e..5542682 100644
--- a/src/htstools.h
+++ b/src/htstools.h
@@ -60,6 +60,7 @@ void longfile_to_83(int mode, char *n83, char *save);
HTS_INLINE int __rech_tageq(const char *adr, const char *s);
HTS_INLINE int __rech_tageqbegdigits(const char *adr, const char *s);
HTS_INLINE int rech_tageq_all(const char *adr, const char *s);
+int hts_template_format(FILE *const out, const char *format, ...);
#define rech_tageq(adr,s) \
( \