Jonathan Nieder wrote: > I have attached > generic-is-binary.c to pin this down; could you try: > > uname -r > dpkg -l libc6 > gcc -Wall -W -O -o generic-is-binary generic-is-binary.c > <M.out ./generic-is-binary M.out > > If M.out (but not stdin) is reported to be binary, great: git is > exonerated, and we have an independent test case. > > If that doesn’t work, it would be nice to learn where the unexpected > zero bytes are. The attached xdiff-debug.patch asks > "git diff --no-index M.out 4.out" which bytes it thinks are null.
Attached this time, sorry. Jonathan
#include <stdlib.h> #include <string.h> #include <stdarg.h> #include <stdio.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <unistd.h> #include <fcntl.h> static int xprintf(const char *fmt, ...); static int buffer_is_binary(const char *ptr, size_t size); static int check_stdin(void); static int check_file(const char *path); int main(int argc, const char * const argv[]) { int result = 0; if (argc != 2) { fprintf(stderr, "usage: generic-is-binary <path> < <path>\n"); exit(1); } result |= check_stdin(); result |= check_file(argv[1]); return result; } static int buffer_is_binary(const char *ptr, size_t sz) { return !!memchr(ptr, 0, sz); } static int check_stdin(void) { static char in_buf[8000]; char *bufp = in_buf; char *buf_end = in_buf + sizeof(in_buf); ssize_t n; while ((n = read(0, bufp, buf_end - bufp))) { if (n < 0) { perror("stdin: read"); return -1; } bufp += n; } return xprintf("stdin is%s binary\n", buffer_is_binary(in_buf, bufp - in_buf) ? "" : " not"); } static ssize_t size(const char *path) { struct stat st; if (lstat(path, &st) < 0) { fprintf(stderr, "%s: lstat: %s\n", path, strerror(errno)); return -1; } return st.st_size; } static int check_file(const char *path) { ssize_t sz; int fd, result; void *data; if ((sz = size(path)) < 0) return -1; if ((fd = open(path, O_RDONLY)) < 0) { fprintf(stderr, "%s: open: %s\n", path, strerror(errno)); return -1; } data = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0); if (data == MAP_FAILED) { fprintf(stderr, "%s: mmap: %s\n", path, strerror(errno)); close(fd); return -1; } if (close(fd)) { fprintf(stderr, "%s: close: %s\n", path, strerror(errno)); return -1; } result = xprintf("%s is%s binary\n", path, buffer_is_binary(data, sz) ? "" : " not"); if (munmap(data, sz)) { fprintf(stderr, "%s: munmap: %s\n", path, strerror(errno)); return -1; } return result; } static int xprintf(const char *fmt, ...) { int result = 0; va_list ap; va_start(ap, fmt); if (vprintf(fmt, ap) < 0) result = -1; va_end(ap); return result; }
diff --git a/xdiff-interface.c b/xdiff-interface.c index 01f14fb..b5b103e 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -223,7 +223,15 @@ int buffer_is_binary(const char *ptr, unsigned long size) { if (FIRST_FEW_BYTES < size) size = FIRST_FEW_BYTES; - return !!memchr(ptr, 0, size); + char *null = memchr(ptr, 0, size); + + fprintf(stderr, "buffer_is_binary(): "); + if (null) + fprintf(stderr, "true; first null offset: %d\n", + (int)(null - ptr)); + else + fprintf(stderr, "false\n"); + return !!null; } struct ff_regs {