diff options
context:
space:
mode:
-rw-r--r--source/ui-blame.c14
-rw-r--r--source/ui-blob.c19
-rw-r--r--source/ui-tree.c5
3 files changed, 33 insertions, 5 deletions
diff --git a/source/ui-blame.c b/source/ui-blame.c
index 80512a0..a7010d0 100644
--- a/source/ui-blame.c
+++ b/source/ui-blame.c
@@ -307,7 +307,19 @@ static void print_blame_page(const struct object_id *oid, const char *path,
cgit_tree_link("tree", NULL, NULL, ctx.qry.head, rev, path);
html(")\n");
- if (buffer_is_binary(buf, size)) {
+ // A NUL past the window buffer_is_binary sniffs would end html_txt
+ // early while the hash and line number columns still cover the whole
+ // file, so a blob holding one anywhere is treated as binary too.
+ if (buffer_is_binary(buf, size) || memchr(buf, 0, size)) {
+ struct blame_entry *ent = sb.ent, *next;
+
+ // The scoreboard is normally consumed by the column passes,
+ // so this early exit has to release it itself.
+ for (; ent; ent = next) {
+ next = ent->next;
+ free(ent);
+ }
+ free((void *)sb.final_buf);
html("<div class='error'>blob is binary.</div>");
goto cleanup;
}
diff --git a/source/ui-blob.c b/source/ui-blob.c
index beb968b..db1d0c1 100644
--- a/source/ui-blob.c
+++ b/source/ui-blob.c
@@ -126,10 +126,23 @@ int cgit_print_file(char *path, const char *head, int file_only, int html_escape
// html_txt wants a terminated string, and git leaves a spare byte
// past every object it reads, so this write stays in the allocation.
buf[size] = '\0';
- if (html_escape)
- html_txt(buf);
- else
+ if (html_escape) {
+ // html_txt stops at a NUL, so a blob holding one is written
+ // segment by segment with a replacement character standing in
+ // for each NUL byte, rather than silently cut short.
+ const char *p = buf, *end = buf + size;
+
+ while (p < end) {
+ html_txt(p);
+ p += strlen(p);
+ while (p < end && !*p) {
+ html("\xef\xbf\xbd");
+ p++;
+ }
+ }
+ } else {
html_raw(buf, size);
+ }
free(buf);
return 0;
}
diff --git a/source/ui-tree.c b/source/ui-tree.c
index 7d24d53..7df7375 100644
--- a/source/ui-tree.c
+++ b/source/ui-tree.c
@@ -191,7 +191,10 @@ static bool print_object(const struct object_id *oid, const char *path,
"Error reading object %s", oid_to_hex(oid));
return false;
}
- is_binary = buffer_is_binary(buf, size);
+ // buffer_is_binary only sniffs the front of the blob, and a NUL past
+ // that window would end the escaped text render early while the line
+ // number column still counts the whole file, so check the rest too.
+ is_binary = buffer_is_binary(buf, size) || memchr(buf, 0, size);
cgit_set_title_from_path(path);