Skip to content

Commit 283c228

Browse files
authored
Merge pull request #3541 from felixhandte/fix-setvbuf-segfault
Avoid Segfault Caused by Calling `setvbuf()` on Null File Pointer
2 parents e769da1 + 957a0ae commit 283c228

File tree

4 files changed

+57
-12
lines changed

4 files changed

+57
-12
lines changed

programs/fileio.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -649,18 +649,24 @@ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
649649
#endif
650650
if (f == NULL) {
651651
DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno));
652+
} else {
653+
/* An increased buffer size can provide a significant performance
654+
* boost on some platforms. Note that providing a NULL buf with a
655+
* size that's not 0 is not defined in ANSI C, but is defined in an
656+
* extension. There are three possibilities here:
657+
* 1. Libc supports the extended version and everything is good.
658+
* 2. Libc ignores the size when buf is NULL, in which case
659+
* everything will continue as if we didn't call `setvbuf()`.
660+
* 3. We fail the call and execution continues but a warning
661+
* message might be shown.
662+
* In all cases due execution continues. For now, I believe that
663+
* this is a more cost-effective solution than managing the buffers
664+
* allocations ourselves (will require an API change).
665+
*/
666+
if (setvbuf(f, NULL, _IOFBF, 1 MB)) {
667+
DISPLAYLEVEL(2, "Warning: setvbuf failed for %s\n", dstFileName);
668+
}
652669
}
653-
/* An increased buffer size can provide a significant performance boost on some platforms.
654-
* Note that providing a NULL buf with a size that's not 0 is not defined in ANSI C, but is defined
655-
* in an extension. There are three possibilities here -
656-
* 1. Libc supports the extended version and everything is good.
657-
* 2. Libc ignores the size when buf is NULL, in which case everything will continue as if we didn't
658-
* call `setvbuf`.
659-
* 3. We fail the call and execution continues but a warning message might be shown.
660-
* In all cases due execution continues. For now, I believe that this is a more cost-effective
661-
* solution than managing the buffers allocations ourselves (will require an API change). */
662-
if(setvbuf(f, NULL, _IOFBF, 1 MB))
663-
DISPLAYLEVEL(2, "Warning: setvbuf failed for %s\n", dstFileName);
664670
return f;
665671
}
666672
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/sh
2+
3+
# motivated by issue #3523
4+
5+
datagen > file
6+
mkdir out
7+
chmod 000 out
8+
9+
zstd file -q --trace-file-stat -o out/file.zst
10+
zstd -tq out/file.zst
11+
12+
chmod 777 out
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Trace:FileStat: > UTIL_isLink(file)
2+
Trace:FileStat: < 0
3+
Trace:FileStat: > UTIL_isConsole(2)
4+
Trace:FileStat: < 0
5+
Trace:FileStat: > UTIL_getFileSize(file)
6+
Trace:FileStat: > UTIL_stat(-1, file)
7+
Trace:FileStat: < 1
8+
Trace:FileStat: < 65537
9+
Trace:FileStat: > UTIL_stat(-1, file)
10+
Trace:FileStat: < 1
11+
Trace:FileStat: > UTIL_isDirectoryStat()
12+
Trace:FileStat: < 0
13+
Trace:FileStat: > UTIL_stat(-1, file)
14+
Trace:FileStat: < 1
15+
Trace:FileStat: > UTIL_isSameFile(file, out/file.zst)
16+
Trace:FileStat: > UTIL_stat(-1, file)
17+
Trace:FileStat: < 1
18+
Trace:FileStat: > UTIL_stat(-1, out/file.zst)
19+
Trace:FileStat: < 0
20+
Trace:FileStat: < 0
21+
Trace:FileStat: > UTIL_isRegularFile(out/file.zst)
22+
Trace:FileStat: > UTIL_stat(-1, out/file.zst)
23+
Trace:FileStat: < 0
24+
Trace:FileStat: < 0
25+
zstd: out/file.zst: Permission denied
26+
zstd: can't stat out/file.zst : Permission denied -- ignored

tests/cli-tests/run.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,8 @@ def _run_script(self, script: str, cwd: str) -> None:
535535
subprocess.run(
536536
args=[script],
537537
stdin=subprocess.DEVNULL,
538-
capture_output=True,
538+
stdout=subprocess.PIPE,
539+
stderr=subprocess.PIPE,
539540
cwd=cwd,
540541
env=env,
541542
check=True,

0 commit comments

Comments
 (0)