Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 33a5f2a

Browse files
committed
Fix BZ2File.(x)readlines() for files without a newline.
1 parent f755432 commit 33a5f2a

3 files changed

Lines changed: 51 additions & 9 deletions

File tree

Lib/test/test_bz2.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def decompress(self, data):
3737
return bz2.decompress(data)
3838

3939
class BZ2FileTest(BaseTest):
40-
"Test MCRYPT type miscelaneous methods."
40+
"Test BZ2File type miscellaneous methods."
4141

4242
def setUp(self):
4343
self.filename = TESTFN
@@ -245,6 +245,22 @@ def testModeU(self):
245245
self.assertEqual(f.tell(), len(self.DATA))
246246
f.close()
247247

248+
def testBug1191043(self):
249+
# readlines() for files containing no newline
250+
data = 'BZh91AY&SY\xd9b\x89]\x00\x00\x00\x03\x80\x04\x00\x02\x00\x0c\x00 \x00!\x9ah3M\x13<]\xc9\x14\xe1BCe\x8a%t'
251+
f = open(self.filename, "wb")
252+
f.write(data)
253+
f.close()
254+
bz2f = BZ2File(self.filename)
255+
lines = bz2f.readlines()
256+
bz2f.close()
257+
self.assertEqual(lines, ['Test'])
258+
bz2f = BZ2File(self.filename)
259+
xlines = bz2f.xreadlines()
260+
bz2f.close()
261+
self.assertEqual(lines, ['Test'])
262+
263+
248264
class BZ2CompressorTest(BaseTest):
249265
def testCompress(self):
250266
# "Test BZ2Compressor.compress()/flush()"

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,9 @@ Core and builtins
15701570
Extension modules
15711571
-----------------
15721572

1573+
- Fix bz2.BZ2File.(x)readlines() for files containing one line without
1574+
newlines.
1575+
15731576
- Added socket.getservbyport(), and make the second argument in
15741577
getservbyname() and getservbyport() optional.
15751578

Modules/bz2module.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ static char __author__[] =
2222
Gustavo Niemeyer <[email protected]>\n\
2323
";
2424

25+
/* Our very own off_t-like type, 64-bit if possible */
26+
/* copied from Objects/fileobject.c */
27+
#if !defined(HAVE_LARGEFILE_SUPPORT)
28+
typedef off_t Py_off_t;
29+
#elif SIZEOF_OFF_T >= 8
30+
typedef off_t Py_off_t;
31+
#elif SIZEOF_FPOS_T >= 8
32+
typedef fpos_t Py_off_t;
33+
#else
34+
#error "Large file support, but neither off_t nor fpos_t is large enough."
35+
#endif
36+
2537
#define BUF(v) PyString_AS_STRING((PyStringObject *)v)
2638

2739
#define MODE_CLOSED 0
@@ -405,7 +417,9 @@ Util_ReadAhead(BZ2FileObject *f, int bufsize)
405417
Util_DropReadAhead(f);
406418
}
407419
if (f->mode == MODE_READ_EOF) {
408-
return -1;
420+
f->f_bufptr = f->f_buf;
421+
f->f_bufend = f->f_buf;
422+
return 0;
409423
}
410424
if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) {
411425
return -1;
@@ -682,13 +696,13 @@ BZ2File_readlines(BZ2FileObject *self, PyObject *args)
682696
}
683697
totalread += nread;
684698
p = memchr(buffer+nfilled, '\n', nread);
685-
if (p == NULL) {
699+
if (!shortread && p == NULL) {
686700
/* Need a larger buffer to fit this line */
687701
nfilled += nread;
688702
buffersize *= 2;
689703
if (buffersize > INT_MAX) {
690704
PyErr_SetString(PyExc_OverflowError,
691-
"line is longer than a Python string can hold");
705+
"line is longer than a Python string can hold");
692706
goto error;
693707
}
694708
if (big_buffer == NULL) {
@@ -705,11 +719,11 @@ BZ2File_readlines(BZ2FileObject *self, PyObject *args)
705719
_PyString_Resize(&big_buffer, buffersize);
706720
buffer = PyString_AS_STRING(big_buffer);
707721
}
708-
continue;
722+
continue;
709723
}
710724
end = buffer+nfilled+nread;
711725
q = buffer;
712-
do {
726+
while (p != NULL) {
713727
/* Process complete lines */
714728
p++;
715729
line = PyString_FromStringAndSize(q, p-q);
@@ -721,7 +735,7 @@ BZ2File_readlines(BZ2FileObject *self, PyObject *args)
721735
goto error;
722736
q = p;
723737
p = memchr(q, '\n', end-q);
724-
} while (p != NULL);
738+
}
725739
/* Move the remaining incomplete line to the start */
726740
nfilled = end-q;
727741
memmove(buffer, q, nfilled);
@@ -962,7 +976,8 @@ static PyObject *
962976
BZ2File_seek(BZ2FileObject *self, PyObject *args)
963977
{
964978
int where = 0;
965-
long offset;
979+
PyObject *offobj;
980+
Py_off_t offset;
966981
char small_buffer[SMALLCHUNK];
967982
char *buffer = small_buffer;
968983
size_t buffersize = SMALLCHUNK;
@@ -973,7 +988,15 @@ BZ2File_seek(BZ2FileObject *self, PyObject *args)
973988
int rewind = 0;
974989
PyObject *ret = NULL;
975990

976-
if (!PyArg_ParseTuple(args, "l|i:seek", &offset, &where))
991+
if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where))
992+
return NULL;
993+
#if !defined(HAVE_LARGEFILE_SUPPORT)
994+
offset = PyInt_AsLong(offobj);
995+
#else
996+
offset = PyLong_Check(offobj) ?
997+
PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
998+
#endif
999+
if (PyErr_Occurred())
9771000
return NULL;
9781001

9791002
ACQUIRE_LOCK(self);

0 commit comments

Comments
 (0)