File: | src/unrrdu/undos.c |
Location: | line 104, column 14 |
Description: | Array access (from variable 'data') results in a null pointer dereference |
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" | |||
28 | static 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 | ||||
45 | static void | |||
46 | undosConvert(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); | |||
| ||||
51 | airArray *dataArr; | |||
52 | unsigned int ci; | |||
53 | int car, numBad, willConvert; | |||
54 | airPtrPtrUnion appu; | |||
55 | ||||
56 | mop = airMopNew(); | |||
57 | if (!airStrlen(name)) { | |||
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) { | |||
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) { | |||
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) { | |||
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) { | |||
99 | if (!quiet) { | |||
100 | fprintf(stderr__stderrp, "%s: internal allocation error #2\n", me); | |||
101 | } | |||
102 | airMopError(mop); return; | |||
103 | } | |||
104 | data[ci] = car; | |||
| ||||
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 | ||||
221 | int | |||
222 | unrrdu_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 | ||||
261 | UNRRDU_CMD_HIDE(undos, INFO)unrrduCmd unrrdu_undosCmd = { "undos", "Converts DOS text files to normal, and more" , unrrdu_undosMain, 1 }; |