diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Harden the request path, scan and error recovery
Diffstat (limited to '')
-rw-r--r--source/html.c32
1 file changed, 28 insertions, 4 deletions
diff --git a/source/html.c b/source/html.c
index 5972d97..a1d244b 100644
--- a/source/html.c
+++ b/source/html.c
@@ -9,6 +9,7 @@
*/
#include "cgit.h"
+#include "cache.h"
#include "html.h"
#define HTML_WRITE_BUFSIZE (64 * 1024)
@@ -58,8 +59,22 @@ static void write_out(const char *data, size_t size)
{
// A blob or snapshot is well past what one write can move onto a
// pipe, so short writes are resumed rather than reported.
- if (write_in_full(STDOUT_FILENO, data, size) < 0)
- die_errno("write error on html output");
+ while (size) {
+ ssize_t written = xwrite(STDOUT_FILENO, data, size);
+
+ if (written < 0)
+ break;
+ data += written;
+ size -= written;
+ }
+ if (!size)
+ return;
+ // While a cache slot is being filled stdout is a file, and a full disk
+ // must not cost the visitor the page. Abandoning the fill puts stdout
+ // back on the client along with what the file already holds, so only
+ // the rest is written again.
+ if (!cache_abandon_fill() || write_in_full(STDOUT_FILENO, data, size) < 0)
+ die_errno("Unable to write the page");
}
/*
@@ -111,6 +126,11 @@ void html_flush(void)
write_out(out_buf, len);
}
+void html_discard(void)
+{
+ out_len = 0;
+}
+
void html_capture_begin(struct strbuf *sb)
{
html_flush();
@@ -191,7 +211,7 @@ ssize_t html_ntxt(const char *txt, size_t len)
if (len > SSIZE_MAX)
return -1;
- left = (ssize_t) len;
+ left = (ssize_t)len;
while (p && *p && left--) {
int c = *p;
if (c == '<' || c == '>' || c == '&') {
@@ -227,6 +247,7 @@ void html_attrf(const char *format, ...)
void html_attr(const char *txt)
{
const char *p = txt;
+
while (p && *p) {
int c = *p;
if (c == '<' || c == '>' || c == '\'' || c == '\"' || c == '&') {
@@ -252,6 +273,7 @@ void html_attr(const char *txt)
void html_url_path(const char *txt)
{
const char *p = txt;
+
while (p && *p) {
unsigned char c = *p;
// A raw ampersand or plus is legal in a URL path, but this
@@ -274,6 +296,7 @@ void html_url_path(const char *txt)
void html_url_arg(const char *txt)
{
const char *p = txt;
+
while (p && *p) {
unsigned char c = *p;
const char *esc = url_escape_table[c];
@@ -293,6 +316,7 @@ void html_url_arg(const char *txt)
void html_header_arg_in_quotes(const char *txt)
{
const char *p = txt;
+
while (p && *p) {
unsigned char c = *p;
const char *esc = NULL;
@@ -379,7 +403,7 @@ int html_include(const char *filename)
size_t len;
if (!(f = fopen(filename, "r"))) {
- fprintf(stderr, "[cgit] Error including file %s: %s (%d)\n", filename, strerror(errno), errno);
+ fprintf(stderr, "[cgit] Unable to include %s: %s (%d)\n", filename, strerror(errno), errno);
return -1;
}
while ((len = fread(buf, 1, sizeof(buf), f)) > 0)