I forgot to update the length of the new string. ============================
$OpenBSD$ Index: ex/ex_source.c --- ex/ex_source.c.orig +++ ex/ex_source.c @@ -38,8 +38,8 @@ int ex_source(SCR *sp, EXCMD *cmdp) { struct stat sb; - int fd, len; - char *bp; + int fd, len, i; + char *bp, c; char *name, *np; size_t nlen; CHAR_T *wp; @@ -64,8 +64,19 @@ ex_source(SCR *sp, EXCMD *cmdp) errno = ENOMEM; goto err; } - - MALLOC(sp, bp, char *, (size_t)sb.st_size + 1); + i = 0; + for (len = 0; len < sb.st_size; ++len) { + if ((rc = read(fd, &c, 1)) <= 0) { + if (rc == 0) + errno = EIO; + (void)close(fd); + goto err; + } + if (c == '|') + ++i; + } + lseek(fd, 0, SEEK_SET); + MALLOC(sp, bp, char *, (size_t)sb.st_size + 1 + i); if (bp == NULL) { (void)close(fd); return (1); @@ -73,18 +84,28 @@ ex_source(SCR *sp, EXCMD *cmdp) bp[sb.st_size] = '\0'; /* Read the file into memory. */ - len = read(fd, bp, (int)sb.st_size); + np = bp; + for (len = 0; len < sb.st_size; ++len, ++np) { + if ((rc = read(fd, np, 1)) <= 0) { + len = rc; + if (len == 0) + errno = EIO; + break; + } + if (*np == '|') { + *np = CH_LITERAL; + *++np = '|'; + } + } (void)close(fd); - if (len == -1 || len != sb.st_size) { - if (len != sb.st_size) - errno = EIO; + if (len != sb.st_size) { free(bp); err: msgq_str(sp, M_SYSERR, name, "%s"); return (1); - } + } np = strdup(name); - if (CHAR2INT(sp, bp, (size_t)sb.st_size + 1, wp, wlen)) + if (CHAR2INT(sp, bp, (size_t)sb.st_size + 1 + i, wp, wlen)) msgq(sp, M_ERR, "323|Invalid input. Truncated."); /* Put it on the ex queue. */ rc = ex_run_str(sp, np, wp, wlen - 1, 1, 0);