```C=0 int _IO_setvbuf (FILE *fp, char *buf, int mode, size_t size) { int result; CHECK_FILE (fp, EOF); _IO_acquire_lock (fp); switch (mode) { . . . case _IONBF: fp->_flags &= ~_IO_LINE_BUF; fp->_flags |= _IO_UNBUFFERED; buf = NULL; size = 0; break; default: result = EOF; goto unlock_return; } result = _IO_SETBUF (fp, buf, size) == NULL ? EOF : 0; unlock_return: _IO_release_lock (fp); return result; } libc_hidden_def (_IO_setvbuf) weak_alias (_IO_setvbuf, setvbuf) ``` ![image](https://hackmd.io/_uploads/SyxJc-v-1l.png) ![image](https://hackmd.io/_uploads/SyUWq-wWkl.png) ![image](https://hackmd.io/_uploads/B1rrq-vW1g.png) ![image](https://hackmd.io/_uploads/Syzw5Wvb1x.png) ![image](https://hackmd.io/_uploads/H1NY5ZDZkg.png) ![image](https://hackmd.io/_uploads/r1yRqZwZ1g.png) ![image](https://hackmd.io/_uploads/rJpbj-wW1x.png) ## Summary ```C setvbuf(stdout, 0, 2, 0) |_ _IO_setvbuf(stdout, 0, 2, 0) |_ _IO_new_file_setbuf(stdout, NULL, 0) |_ _IO_default_setbuf(stdout, NULL, 0) |_ _IO_new_file_sync(stdout) (1) |_ _IO_do_flush(stdout) (2) |_ _IO_do_write(stdout, stdout->_IO_write_base, stdout->_IO_write_ptr - stdout->_IO_write_base) |_ new_do_write(stdout, stdout->_IO_write_base, stdout->_IO_write_ptr - stdout->_IO_write_base) (3) |_ _IO_new_file_write(stdout, stdout->_IO_write_base, stdout->_IO_write_ptr - stdout->_IO_write_base) (4) |_ write(stdout, stdout->_IO_write_base, stdout->_IO_write_ptr - stdout->_IO_write_base) INIT: _flags = "input" _flags & ~_IO_LINE_BUF (_IO_LINE_BUF=0x0200) _flags = _flags | _IO_UNBUFFERED (_IO_UNBUFFERED=0x0002) Conditions: FROM (1) -> (2): stdout->_IO_write_ptr > stdout-> _IO_write_base FROM (2) -> (3): stdout->_mode <= 0 FROM (3) -> (4): stdout->_flags & _IO_IS_APPENDING != 0 (_IO_IS_APPENDING=0x1000) _IO_buf_base = NULL ``` ## Test ```C #include <stdio.h> int main(){ // libc 2.38 long long new_IO_write_base; setvbuf(stdin, 0, 2, 0); setvbuf(stdout, 0, 2, 0); setvbuf(stderr, 0, 2, 0); new_IO_write_base = (long long)stdout->_IO_write_base ^ 0x43; //set the last byte of _IO_write_base to 0 stdout->_flags = 0xfbad1000; stdout->_IO_write_base = (char *)new_IO_write_base; stdout->_IO_buf_base = NULL; stdout->_mode = 0; // trigger setvbuf(stdout, 0, 2, 0); return 0; } ``` ![image](https://hackmd.io/_uploads/BkZmKxU-1l.png)