-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serious interpreter crash and/or arbitrary memory leak using .read() on writable file #49927
Comments
(tested and verified on Windows and Solaris SPARC) Running this code in Python 2.4, 2.5 or 2.6 (all minor versions) f=open("anyfile","w")
f.write("garbage")
f.readline() Mac OS X and Linux appear to simply throw an "IOError: [Errno 9] Bad Under Solaris, it is further possible to segfault the interpreter with In the former case, it appears as if the data is simply read from the In Python 3.0, file objects opened with "w" don't even support any .read |
OK, it's not a memory leak, rather, it's something leaking from the |
related: windows: 2.6.2 mingw/ 2.6.4 msvc builds linux is ok f.read() return '' as expected |
It seems like this is actually a problem in Windows libc or something (tested using MinGW on Windows XP): #include <stdio.h>
main() {
FILE *f = fopen("test", "wb");
fwrite("test", 1, 4, f);
char buf[2048];
size_t k = fread(buf, 1, 2048, f);
printf("%d\n", k);
int i=0;
for(; i<k; i++) printf("%02x", buf[i]);
} This causes a lot of garbage to be printed out. Removing the fwrite causes "0" to be printed with no further output. The garbage is not from the uninitialized buffer, since I've verified that the original contents of the buffer are not what is being printed out. Furthermore, adjusting 2048 produces a maximum output of 4092 bytes (even with 9999 in place of 2048). Short of simply denying read() on writable files, I don't really see an easy way around this libc bug. |
I wonder if this is technically a bug. The stream is not opened for reading and yet you do an fread. I quickly glanced through the Regarding the last C example. Also here, you do not open using "w+". |
Bug or not, this can be handled since fread sets EBADF on Windows. |
The patch should come with a test. |
I see that a complete errno based solution would get messy. To avoid #if defined(EBADF)
#define ERRNO_EBADF(x) ((x) == EBADF)
#else
#define ERRNO_EBADF(x) 0
#endif Then, additional checks would need to be added to get_line, I think the right thing is to add a field f_modeflags to the file |
I think checking errno would be fine (provided it eliminates all variations ot this bug). |
An errno+ferror approach works except for two cases: (1) MS fgets() does not consider reading from a write-only stream (2) OpenSolaris sets errno unreliably after getc. I do not know how to get around those without using OS specifics. |
Ok, then perhaps it's better to have some internal {readable, writable} |
The new patch takes over the logic from fileio.c. Tested on Linux, Windows x86/x64 and OpenSolaris. |
Hmm, test_file.py is for the new IO library (backported from 3.x). You should use test_file2k.py for tests against the 2.x file object. Also, readinto() should take something such as a bytearray() as argument, not a string. |
Thanks Antoine, I fixed both issues. |
Oh and the following line shouldn't be needed: data = b'xxx' if 'b' in mode else u'xxx' Since old-style file objects always take bytestrings (it's harmless, though, because the unicode string will be implicitly converted). |
Ok, I'll fix that. Perhaps I should also remove the comment in err_mode(). I wonder if the ValueError in fileio.c is intentional: >>> import io
>>> f = io.open("testfile", "w")
>>> f.write("xxx")
3
>>> f.read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: not readable
>>>
>>> f = io.FileIO("testfile", "w")
>>> f.write("xxx")
3
>>> f.read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: File not open for reading |
I don't know, but this would be the subject of a separate issue anyway. |
The patch was committed in r77989 (trunk) and r77990 (2.6). Thank you Stefan! |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: