Skip to content

Commit a99edcb

Browse files
More careful about free() before any STOP(), #ifndef location
1 parent f72e46b commit a99edcb

File tree

1 file changed

+74
-38
lines changed

1 file changed

+74
-38
lines changed

src/fwrite.c

Lines changed: 74 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -804,20 +804,31 @@ void fwriteMain(fwriteMainArgs args)
804804
if (args.is_gzip) {
805805
// alloc zlib streams
806806
thread_streams = (z_stream*) malloc(nth * sizeof(z_stream));
807+
if (!thread_streams) {
808+
// # nocov start
809+
free(buffPool);
810+
STOP(_("Failed to allocated %d bytes for threads_streams."), (int)(nth * sizeof(z_stream)));
811+
// # nocov end
812+
}
807813
if (verbose) {
808814
DTPRINT(_("Allocate %zu bytes for thread_streams\n"), nth * sizeof(z_stream));
809815
}
810-
if (!thread_streams)
811-
STOP(_("Failed to allocated %d bytes for threads_streams."), (int)(nth * sizeof(z_stream))); // #nocov
812816
// VLA on stack should be fine for nth structs; in zlib v1.2.11 sizeof(struct)==112 on 64bit
813817
// not declared inside the parallel region because solaris appears to move the struct in
814818
// memory when the #pragma omp for is entered, which causes zlib's internal self reference
815819
// pointer to mismatch, #4099
816820

817821
// compute zbuffSize which is the same for each thread
818822
z_stream *stream = thread_streams;
819-
if (init_stream(stream) != Z_OK)
820-
STOP(_("Can't init stream structure for deflateBound")); // #nocov
823+
if (init_stream(stream) != Z_OK) {
824+
// # nocov start
825+
free(buffPool);
826+
#ifndef NOZLIB
827+
free(thread_streams);
828+
#endif
829+
STOP(_("Can't init stream structure for deflateBound"));
830+
// # nocov end
831+
}
821832
zbuffSize = deflateBound(stream, buffSize);
822833
if (verbose)
823834
DTPRINT(_("zbuffSize=%d returned from deflateBound\n"), (int)zbuffSize);
@@ -832,6 +843,9 @@ void fwriteMain(fwriteMainArgs args)
832843
if (!zbuffPool) {
833844
// # nocov start
834845
free(buffPool);
846+
#ifndef NOZLIB
847+
free(thread_streams);
848+
#endif
835849
STOP(_("Unable to allocate %zu MiB * %d thread compressed buffers; '%d: %s'. Please read ?fwrite for nThread, buffMB and verbose options."),
836850
zbuffSize / MEGA, nth, errno, strerror(errno));
837851
// # nocov end
@@ -880,11 +894,18 @@ void fwriteMain(fwriteMainArgs args)
880894
DTPRINT("%s", buff);
881895
} else {
882896
int ret0=0, ret1=0, ret2=0;
883-
if (args.is_gzip) {
884897
#ifndef NOZLIB
898+
if (args.is_gzip) {
885899
z_stream *stream = thread_streams;
886-
if (init_stream(stream) != Z_OK)
887-
STOP(_("Can't init stream structure for writing header")); // #nocov
900+
if (init_stream(stream) != Z_OK) {
901+
// # nocov start
902+
free(buffPool);
903+
#ifndef NOZLIB
904+
free(thread_streams);
905+
free(zbuffPool);
906+
#endif
907+
STOP(_("Can't init stream structure for writing header"));
908+
}
888909
char* zbuff = zbuffPool;
889910
// write minimal gzip header
890911
char* header = "\037\213\10\0\0\0\0\0\0\3";
@@ -900,14 +921,21 @@ void fwriteMain(fwriteMainArgs args)
900921
ret2 = WRITE(f, zbuff, (int)zbuffUsed);
901922
compress_len += zbuffUsed;
902923
}
903-
#endif
904924
} else {
925+
#endif
905926
ret2 = WRITE(f, buff, (int)(ch-buff));
927+
#ifndef NOZLIB
906928
}
929+
#endif
907930
if (ret0 == -1 || ret1 || ret2 == -1) {
908931
// # nocov start
909932
int errwrite = errno; // capture write errno now in case close fails with a different errno
910933
CLOSE(f);
934+
free(buffPool);
935+
#ifndef NOZLIB
936+
free(thread_streams);
937+
free(zbuffPool);
938+
#endif
911939
if (ret0 == -1) STOP(_("Can't write gzip header error: %d"), ret0);
912940
else if (ret1) STOP(_("Compress gzip error: %d"), ret1);
913941
else STOP(_("%s: '%s'"), strerror(errwrite), args.filename);
@@ -922,8 +950,15 @@ void fwriteMain(fwriteMainArgs args)
922950
if (args.nrow == 0) {
923951
if (verbose)
924952
DTPRINT(_("No data rows present (nrow==0)\n"));
925-
if (f != -1 && CLOSE(f))
926-
STOP(_("%s: '%s'"), strerror(errno), args.filename); // # nocov
953+
if (f != -1 && CLOSE(f)) {
954+
// # nocov start
955+
free(buffPool);
956+
#ifndef NOZLIB
957+
free(thread_streams);
958+
free(zbuffPool);
959+
#endif
960+
STOP(_("%s: '%s'"), strerror(errno), args.filename);
961+
}
927962
return;
928963
}
929964

@@ -1023,25 +1058,27 @@ void fwriteMain(fwriteMainArgs args)
10231058
if (f == -1) {
10241059
*ch='\0'; // standard C string end marker so DTPRINT knows where to stop
10251060
DTPRINT("%s", myBuff);
1026-
} else if (args.is_gzip) {
1061+
} else
10271062
#ifndef NOZLIB
1028-
ret = WRITE(f, myzBuff, (int)myzbuffUsed);
1029-
compress_len += myzbuffUsed;
1063+
if (args.is_gzip) {
1064+
ret = WRITE(f, myzBuff, (int)myzbuffUsed);
1065+
compress_len += myzbuffUsed;
1066+
} else
10301067
#endif
1031-
} else {
1068+
{
10321069
ret = WRITE(f, myBuff, (int)(ch-myBuff));
10331070
}
10341071
if (ret == -1) {
10351072
failed=true; // # nocov
10361073
failed_write=errno; // # nocov
10371074
}
10381075

1039-
if (args.is_gzip) {
10401076
#ifndef NOZLIB
1077+
if (args.is_gzip) {
10411078
crc = crc32_combine(crc, mycrc, mylen);
10421079
len += mylen;
1043-
#endif
10441080
}
1081+
#endif
10451082

10461083
int used = 100 * ((double)(ch - myBuff)) / buffSize; // percentage of original buffMB
10471084
if (used > maxBuffUsedPC)
@@ -1067,36 +1104,35 @@ void fwriteMain(fwriteMainArgs args)
10671104
}
10681105
}
10691106
}
1070-
if (args.is_gzip) {
10711107
#ifndef NOZLIB
1108+
if (args.is_gzip) {
10721109
deflateEnd(mystream);
1073-
#endif
10741110
}
1111+
#endif
10751112

10761113
} // end of parallel for loop
10771114

1078-
/* put a 4-byte integer into a byte array in LSB order */
1079-
#define PUT4(a,b) ((a)[0]=(b), (a)[1]=(b)>>8, (a)[2]=(b)>>16, (a)[3]=(b)>>24)
1080-
1081-
// write gzip tailer with crc and len
1082-
if (args.is_gzip) {
1083-
#ifndef NOZLIB
1084-
unsigned char tail[10];
1085-
tail[0] = 3;
1086-
tail[1] = 0;
1087-
PUT4(tail + 2, crc);
1088-
PUT4(tail + 6, len);
1089-
int ret = WRITE(f, tail, 10);
1090-
compress_len += 10;
1091-
if (ret == -1)
1092-
STOP("Error: can't write gzip tailer"); // # nocov
1093-
#endif
1094-
}
1095-
10961115
free(buffPool);
1116+
10971117
#ifndef NOZLIB
10981118
free(thread_streams);
10991119
free(zbuffPool);
1120+
1121+
/* put a 4-byte integer into a byte array in LSB order */
1122+
#define PUT4(a,b) ((a)[0]=(b), (a)[1]=(b)>>8, (a)[2]=(b)>>16, (a)[3]=(b)>>24)
1123+
1124+
// write gzip tailer with crc and len
1125+
if (args.is_gzip) {
1126+
unsigned char tail[10];
1127+
tail[0] = 3;
1128+
tail[1] = 0;
1129+
PUT4(tail + 2, crc);
1130+
PUT4(tail + 6, len);
1131+
int ret = WRITE(f, tail, 10);
1132+
compress_len += 10;
1133+
if (ret == -1)
1134+
STOP("Error: can't write gzip tailer"); // # nocov
1135+
}
11001136
#endif
11011137

11021138
// Finished parallel region and can call R API safely now.
@@ -1112,12 +1148,12 @@ void fwriteMain(fwriteMainArgs args)
11121148
}
11131149

11141150
if (verbose) {
1115-
if (args.is_gzip) {
11161151
#ifndef NOZLIB
1152+
if (args.is_gzip) {
11171153
DTPRINT("zlib: uncompressed length=%zu (%zu MiB), compressed length=%zu (%zu MiB), ratio=%.1f%%, crc=%x\n",
11181154
len, len / MEGA, compress_len, compress_len / MEGA, len != 0 ? (100.0 * compress_len) / len : 0, crc);
1119-
#endif
11201155
}
1156+
#endif
11211157
DTPRINT("Written %"PRId64" rows in %.3f secs using %d thread%s. MaxBuffUsed=%d%%\n",
11221158
args.nrow, 1.0*(wallclock()-t0), nth, nth ==1 ? "" : "s", maxBuffUsedPC);
11231159
}

0 commit comments

Comments
 (0)