Skip to content

Commit 1a2857b

Browse files
author
kalibera
committed
Improve handling of short (uncompressed) files and error handling in gzcon.
Partially addresses PR#18887. git-svn-id: https://svn.r-project.org/R/trunk@88409 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent fb6baa4 commit 1a2857b

File tree

1 file changed

+50
-36
lines changed

1 file changed

+50
-36
lines changed

src/main/connections.c

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6159,8 +6159,23 @@ Rconnection R_GetConnection(SEXP sConn) {
61596159
/* ------------------- (de)compression functions --------------------- */
61606160

61616161
/* Code for gzcon connections is modelled on gzio.c from zlib 1.2.3 */
6162+
static int gzcon_byte(Rgzconn priv)
6163+
{
6164+
Rconnection icon = priv->con;
61626165

6163-
#define get_byte() (icon->read(&ccc, 1, 1, icon), ccc)
6166+
if (priv->z_eof) return EOF;
6167+
if (priv->s.avail_in == 0) {
6168+
priv->s.avail_in = (uInt) icon->read(priv->buffer, 1, Z_BUFSIZE, icon);
6169+
if (priv->s.avail_in == 0) {
6170+
priv->z_eof = 1;
6171+
return EOF;
6172+
} else if ((int)priv->s.avail_in < 0)
6173+
error("error reading from the connection");
6174+
priv->s.next_in = priv->buffer;
6175+
}
6176+
priv->s.avail_in--;
6177+
return *(priv->s.next_in)++;
6178+
}
61646179

61656180
static Rboolean gzcon_open(Rconnection con)
61666181
{
@@ -6185,44 +6200,53 @@ static Rboolean gzcon_open(Rconnection con)
61856200

61866201
if(con->canread) {
61876202
/* read header */
6188-
char c, ccc, method, flags, dummy[6];
6203+
char c, method, flags;
61896204
unsigned char head[2];
61906205
uInt len;
61916206

6192-
icon->read(head, 1, 2, icon);
6193-
if(head[0] != gz_magic[0] || head[1] != gz_magic[1]) {
6207+
len = (uInt) icon->read(head, 1, 2, icon);
6208+
if ((int)len < 0)
6209+
error("error reading from the connection");
6210+
if(len < 2 || head[0] != gz_magic[0] || head[1] != gz_magic[1]) {
61946211
if(!priv->allow) {
61956212
warning(_("file stream does not have gzip magic number"));
61966213
return FALSE;
61976214
}
6198-
priv->nsaved = 2;
6199-
priv->saved[0] = head[0];
6200-
priv->saved[1] = head[1];
6215+
priv->nsaved = 0;
6216+
if (len >= 1) {
6217+
priv->nsaved++;
6218+
priv->saved[0] = head[0];
6219+
}
6220+
if (len == 2) {
6221+
priv->nsaved++;
6222+
priv->saved[1] = head[1];
6223+
}
62016224
return TRUE;
62026225
}
6203-
icon->read(&method, 1, 1, icon);
6204-
icon->read(&flags, 1, 1, icon);
6226+
method = gzcon_byte(priv);
6227+
flags = gzcon_byte(priv);
62056228
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
62066229
warning(_("file stream does not have valid gzip header"));
62076230
return FALSE;
62086231
}
6209-
icon->read(dummy, 1, 6, icon);
6232+
/* Discard time, xflags and OS code: */
6233+
for (len = 0; len < 6; len++) (void) gzcon_byte(priv);
6234+
62106235
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
6211-
len = (uInt) get_byte();
6212-
len += ((uInt) get_byte()) << 8;
6236+
len = (uInt) gzcon_byte(priv);
6237+
len += ((uInt) gzcon_byte(priv)) << 8;
62136238
/* len is garbage if EOF but the loop below will quit anyway */
6214-
while (len-- != 0 && get_byte() != EOF) ;
6239+
while (len-- != 0 && gzcon_byte(priv) != EOF) ;
62156240
}
62166241
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
6217-
while ((c = get_byte()) != 0 && c != EOF) ;
6242+
while ((c = gzcon_byte(priv)) != 0 && c != EOF) ;
62186243
}
62196244
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
6220-
while ((c = get_byte()) != 0 && c != EOF) ;
6245+
while ((c = gzcon_byte(priv)) != 0 && c != EOF) ;
62216246
}
62226247
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
6223-
for (len = 0; len < 2; len++) (void) get_byte();
6248+
for (len = 0; len < 2; len++) (void) gzcon_byte(priv);
62246249
}
6225-
priv->s.next_in = priv->buffer;
62266250
inflateInit2(&(priv->s), -MAX_WBITS);
62276251
} else {
62286252
/* write a header */
@@ -6293,23 +6317,6 @@ static void gzcon_close(Rconnection con)
62936317
con->isopen = FALSE;
62946318
}
62956319

6296-
static int gzcon_byte(Rgzconn priv)
6297-
{
6298-
Rconnection icon = priv->con;
6299-
6300-
if (priv->z_eof) return EOF;
6301-
if (priv->s.avail_in == 0) {
6302-
priv->s.avail_in = (uInt) icon->read(priv->buffer, 1, Z_BUFSIZE, icon);
6303-
if (priv->s.avail_in == 0) {
6304-
priv->z_eof = 1;
6305-
return EOF;
6306-
}
6307-
priv->s.next_in = priv->buffer;
6308-
}
6309-
priv->s.avail_in--;
6310-
return *(priv->s.next_in)++;
6311-
}
6312-
63136320

63146321
static size_t gzcon_read(void *ptr, size_t size, size_t nitems,
63156322
Rconnection con)
@@ -6319,6 +6326,7 @@ static size_t gzcon_read(void *ptr, size_t size, size_t nitems,
63196326
Bytef *start = (Bytef*) ptr;
63206327
uLong crc;
63216328
int n;
6329+
size_t icread;
63226330

63236331
if (priv->z_err == Z_STREAM_END) return 0; /* EOF */
63246332

@@ -6333,8 +6341,12 @@ static size_t gzcon_read(void *ptr, size_t size, size_t nitems,
63336341
for(i = 0; i < priv->nsaved; i++)
63346342
((char *)ptr)[i] = priv->saved[i];
63356343
priv->nsaved = 0;
6336-
return (nsaved + icon->read((char *) ptr+nsaved, 1, len - nsaved,
6337-
icon))/size;
6344+
icread = icon->read((char *) ptr+nsaved, 1, len - nsaved,
6345+
icon)/size;
6346+
if ((int)icread < 0)
6347+
return icread;
6348+
else
6349+
return nsaved + icread;
63386350
}
63396351
if (len == 1) { /* size must be one */
63406352
if (nsaved > 0) {
@@ -6354,6 +6366,8 @@ static size_t gzcon_read(void *ptr, size_t size, size_t nitems,
63546366
if (priv->s.avail_in == 0 && !priv->z_eof) {
63556367
priv->s.avail_in = (uInt)icon->read(priv->buffer, 1, Z_BUFSIZE, icon);
63566368
if (priv->s.avail_in == 0) priv->z_eof = 1;
6369+
if ((int)priv->s.avail_in < 0)
6370+
return priv->s.avail_in;
63576371
priv->s.next_in = priv->buffer;
63586372
}
63596373
priv->z_err = inflate(&(priv->s), Z_NO_FLUSH);

0 commit comments

Comments
 (0)