Bug Summary

File:src/unrrdu/undos.c
Location:line 104, column 14
Description:Array access (from variable 'data') results in a null pointer dereference

Annotated Source Code

1/*
2 Teem: Tools to process and visualize scientific data and images .
3 Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago
4 Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann
5 Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 (LGPL) as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11 The terms of redistributing and/or modifying this software also
12 include exceptions to the LGPL that facilitate static linking.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with this library; if not, write to Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22*/
23
24#include "unrrdu.h"
25#include "privateUnrrdu.h"
26
27#define INFO"Converts DOS text files to normal, and more" "Converts DOS text files to normal, and more"
28static const char *_unrrdu_undosInfoL =
29 (INFO"Converts DOS text files to normal, and more"
30 ". Normally, it converts LF-CR pairs to just CR, or, with the \"-r\" "
31 "option, convert back to DOS, for whatever sick and "
32 "twisted reason you'd have to do that. Can also handle legacy MAC "
33 "text files (only LF). Unlike the simple sed or perl scripts for "
34 "this purpose, this program is careful to be idempotent. Also, this "
35 "makes an effort to not meddle with binary files (on which this may be "
36 "mistakenly invoked). A message is printed to stderr for all the files "
37 "actually modified. Does various things, some more justified than "
38 "others.\n "
39 "* (not actually based on Nrrd)");
40
41#define CR10 10
42#define LF13 13
43#define BAD_PERC5.0 5.0
44
45static void
46undosConvert(const char *me, char *name, int reverse, int mac,
47 int quiet, int noAction) {
48 airArray *mop;
49 FILE *fin, *fout;
50 char *data=NULL((void*)0);
1
'data' initialized to a null pointer value
51 airArray *dataArr;
52 unsigned int ci;
53 int car, numBad, willConvert;
54 airPtrPtrUnion appu;
55
56 mop = airMopNew();
57 if (!airStrlen(name)) {
2
Taking false branch
58 fprintf(stderr__stderrp, "%s: empty filename\n", me);
59 airMopError(mop); return;
60 }
61
62 /* -------------------------------------------------------- */
63 /* open input file */
64 fin = airFopen(name, stdin__stdinp, "rb");
65 if (!fin) {
3
Assuming 'fin' is non-null
4
Taking false branch
66 if (!quiet) {
67 fprintf(stderr__stderrp, "%s: couldn't open \"%s\" for reading: \"%s\"\n",
68 me, name, strerror(errno(*__error())));
69 }
70 airMopError(mop); return;
71 }
72 airMopAdd(mop, fin, (airMopper)airFclose, airMopOnError);
73
74 /* -------------------------------------------------------- */
75 /* create buffer */
76 appu.c = &data;
77 dataArr = airArrayNew(appu.v, NULL((void*)0), sizeof(char), AIR_STRLEN_HUGE(1024+1));
78 if (!dataArr) {
5
Assuming 'dataArr' is non-null
6
Taking false branch
79 if (!quiet) {
80 fprintf(stderr__stderrp, "%s: internal allocation error #1\n", me);
81 }
82 airMopError(mop); return;
83 }
84 airMopAdd(mop, dataArr, (airMopper)airArrayNuke, airMopAlways);
85
86 /* -------------------------------------------------------- */
87 /* read input file, testing for binary-ness along the way */
88 numBad = 0;
89 car = getc(fin);
90 if (EOF(-1) == car) {
7
Taking false branch
91 if (!quiet) {
92 fprintf(stderr__stderrp, "%s: \"%s\" is empty, skipping ...\n", me, name);
93 }
94 airMopError(mop); return;
95 }
96 do {
97 ci = airArrayLenIncr(dataArr, 1);
98 if (!dataArr->data) {
8
Taking false branch
99 if (!quiet) {
100 fprintf(stderr__stderrp, "%s: internal allocation error #2\n", me);
101 }
102 airMopError(mop); return;
103 }
104 data[ci] = car;
9
Array access (from variable 'data') results in a null pointer dereference
105 numBad += !(isprint(car) || isspace(car));
106 car = getc(fin);
107 } while (EOF(-1) != car && BAD_PERC5.0 > 100.0*numBad/dataArr->len);
108 if (EOF(-1) != car) {
109 if (!quiet) {
110 fprintf(stderr__stderrp, "%s: more than %g%% of \"%s\" is non-printing, "
111 "skipping ...\n", me, BAD_PERC5.0, name);
112 }
113 airMopError(mop); return;
114 }
115 fin = airFclose(fin);
116
117 /* -------------------------------------------------------- */
118 /* see if we really need to do anything */
119 willConvert = AIR_FALSE0;
120 if (!strcmp("-", name)) {
121 willConvert = AIR_TRUE1;
122 } else if (reverse) {
123 for (ci=0; ci<dataArr->len; ci++) {
124 if (mac) {
125 if (CR10 == data[ci]) {
126 willConvert = AIR_TRUE1;
127 break;
128 }
129 } else {
130 if (CR10 == data[ci] && (ci && LF13 != data[ci-1])) {
131 willConvert = AIR_TRUE1;
132 break;
133 }
134 }
135 }
136 } else {
137 for (ci=0; ci<dataArr->len; ci++) {
138 if (mac) {
139 if (LF13 == data[ci]) {
140 willConvert = AIR_TRUE1;
141 break;
142 }
143 } else {
144 if (LF13 == data[ci] && (ci+1<dataArr->len && CR10 == data[ci+1])) {
145 willConvert = AIR_TRUE1;
146 break;
147 }
148 }
149 }
150 }
151 if (!willConvert) {
152 /* no, we don't need to do anything; quietly quit */
153 airMopOkay(mop);
154 return;
155 } else {
156 if (!quiet) {
157 fprintf(stderr__stderrp, "%s: %s \"%s\" %s %s ... \n", me,
158 noAction ? "would convert" : "converting",
159 name,
160 reverse ? "to" : "from",
161 mac ? "MAC" : "DOS");
162 }
163 }
164 if (noAction) {
165 /* just joking, we won't actually write anything.
166 (yes, even if input was stdin) */
167 airMopOkay(mop);
168 return;
169 }
170
171 /* -------------------------------------------------------- */
172 /* open output file */
173 fout = airFopen(name, stdout__stdoutp, "wb");
174 if (!fout) {
175 if (!quiet) {
176 fprintf(stderr__stderrp, "%s: couldn't open \"%s\" for writing: \"%s\"\n",
177 me, name, strerror(errno(*__error())));
178 }
179 airMopError(mop); return;
180 }
181 airMopAdd(mop, fout, (airMopper)airFclose, airMopOnError);
182
183 /* -------------------------------------------------------- */
184 /* write output file */
185 car = 'a';
186 if (reverse) {
187 for (ci=0; ci<dataArr->len; ci++) {
188 if ((mac && CR10 == data[ci])
189 || (CR10 == data[ci] && (ci && LF13 != data[ci-1]))) {
190 car = putc(LF13, fout);
191 if (!mac && EOF(-1) != car) {
192 car = putc(CR10, fout);
193 }
194 } else {
195 car = putc(data[ci], fout);
196 }
197 }
198 } else {
199 for (ci=0; EOF(-1) != car && ci<dataArr->len; ci++) {
200 if ((mac && LF13 == data[ci])
201 || (LF13 == data[ci] && (ci+1<dataArr->len && CR10 == data[ci+1]))) {
202 car = putc(CR10, fout);
203 ci += !mac;
204 } else {
205 car = putc(data[ci], fout);
206 }
207 }
208 }
209 if (EOF(-1) == car) {
210 if (!quiet) {
211 fprintf(stderr__stderrp, "%s: ERROR writing \"%s\" possible data loss !!! "
212 "(sorry)\n", me, name);
213 }
214 }
215 fout = airFclose(fout);
216
217 airMopOkay(mop);
218 return;
219}
220
221int
222unrrdu_undosMain(int argc, const char **argv, const char *me,
223 hestParm *hparm) {
224 /* these are stock for unrrdu */
225 hestOpt *opt = NULL((void*)0);
226 airArray *mop;
227 int pret;
228 char *err;
229 /* these are specific to this command */
230 char **name;
231 int lenName, ni, reverse, quiet, noAction, mac;
232
233 hestOptAdd(&opt, "r", NULL((void*)0), airTypeInt, 0, 0, &reverse, NULL((void*)0),
234 "convert back to DOS, instead of converting from DOS to normal");
235 hestOptAdd(&opt, "q", NULL((void*)0), airTypeInt, 0, 0, &quiet, NULL((void*)0),
236 "never print anything to stderr, even for errors.");
237 hestOptAdd(&opt, "m", NULL((void*)0), airTypeInt, 0, 0, &mac, NULL((void*)0),
238 "deal with legacy MAC text files.");
239 hestOptAdd(&opt, "n", NULL((void*)0), airTypeInt, 0, 0, &noAction, NULL((void*)0),
240 "don't actually write converted files, just pretend to. "
241 "This is useful to see which files WOULD be converted. ");
242 hestOptAdd(&opt, NULL((void*)0), "file", airTypeString, 1, -1, &name, NULL((void*)0),
243 "all the files to convert. Each file will be over-written "
244 "with its converted contents. Use \"-\" to read from stdin "
245 "and write to stdout", &lenName);
246
247 mop = airMopNew();
248 airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);
249 USAGE(_unrrdu_undosInfoL)if (!argc) { hestInfo(__stdoutp, me, (_unrrdu_undosInfoL), hparm
); hestUsage(__stdoutp, opt, me, hparm); hestGlossary(__stdoutp
, opt, hparm); airMopError(mop); return 0; }
;
250 PARSE()if ((pret=hestParse(opt, argc, argv, &err, hparm))) { if (
1 == pret || 2 == pret) { if (!(getenv("UNRRDU_QUIET_QUIT") &&
airEndsWith(err, "[nrrd] _nrrdRead: immediately hit EOF" "\n"
))) { fprintf(__stderrp, "%s: %s\n", me, err); free(err); hestUsage
(__stderrp, opt, me, hparm); hestGlossary(__stderrp, opt, hparm
); } airMopError(mop); return 1; } else { exit(1); } }
;
251 airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);
252
253 for (ni=0; ni<lenName; ni++) {
254 undosConvert(me, name[ni], reverse, mac, quiet, noAction);
255 }
256
257 airMopOkay(mop);
258 return 0;
259}
260
261UNRRDU_CMD_HIDE(undos, INFO)unrrduCmd unrrdu_undosCmd = { "undos", "Converts DOS text files to normal, and more"
, unrrdu_undosMain, 1 }
;