ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 2.16
Committed: Thu Aug 2 18:33:50 2018 UTC (5 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2
Changes since 2.15: +2 -2 lines
Log Message:
Created MAXFMTLEN to guard against buffer overrun attacks in header input

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: glareval.c,v 2.15 2018/01/24 04:39:52 greg Exp $";
3 #endif
4 /*
5 * Compute pixels for glare calculation
6 */
7
8 #include "copyright.h"
9
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "platform.h"
14 #include "rtprocess.h" /* Windows: must come first because of conflicts */
15 #include "glare.h"
16
17 /* maximum rtrace buffer size */
18 #define MAXPIX (4096/(6*sizeof(float)))
19
20 #define MAXSBUF 786432 /* maximum total size of scanline buffer */
21 #define HSIZE 317 /* size of scanline hash table */
22 #define NRETIRE 16 /* number of scanlines to retire at once */
23
24 static SUBPROC rt_pd = SP_INACTIVE; /* process id & descriptors for rtrace */
25
26 FILE *pictfp = NULL; /* picture file pointer */
27 double exposure; /* picture exposure */
28 int pxsiz, pysiz; /* picture dimensions */
29
30 static int curpos; /* current scanline */
31 static long *scanpos; /* scanline positions */
32
33 typedef struct scan {
34 int y; /* scanline position */
35 long lused; /* for LRU replacement */
36 struct scan *next; /* next in this hash or free list */
37 /* followed by the scanline data */
38 } SCAN; /* buffered scanline */
39
40 #define scandata(sl) ((COLR *)((sl)+1))
41 #define shash(y) ((y)%HSIZE)
42
43 static int maxpix; /* maximum number of pixels to buffer */
44
45 static SCAN *freelist; /* scanline free list */
46 static SCAN *hashtab[HSIZE]; /* scanline hash table */
47
48 static long scanbufsiz; /* size of allocated scanline buffer */
49
50 static long ncall = 0L; /* number of calls to getpictscan */
51 static long nread = 0L; /* number of scanlines read */
52 static long nrecl = 0L; /* number of scanlines reclaimed */
53
54 static int wrongformat = 0;
55
56 static SCAN * claimscan(int y);
57 static COLR * getpictscan(int y);
58 static double pict_val(FVECT vd);
59 static void rt_compute(float *pb, int np);
60 static gethfunc getexpos;
61 static SCAN * scanretire(void);
62 static void initscans(void);
63 static void donescans(void);
64
65
66 static SCAN *
67 claimscan( /* claim scanline from buffers */
68 int y
69 )
70 {
71 int hi = shash(y);
72 SCAN *slast;
73 register SCAN *sl;
74
75 for (sl = hashtab[hi]; sl != NULL; sl = sl->next)
76 if (sl->y == y) /* active scanline */
77 return(sl);
78 for (slast = NULL, sl = freelist; sl != NULL; slast = sl, sl = sl->next)
79 if (sl->y == -1 || sl->y == y || sl->next == NULL) {
80 if (slast == NULL) /* remove from free */
81 freelist = sl->next;
82 else
83 slast->next = sl->next;
84 if (sl->y == y) { /* reclaim */
85 sl->next = hashtab[hi];
86 hashtab[hi] = sl;
87 nrecl++;
88 }
89 return(sl);
90 }
91 return(scanretire()); /* need more free scanlines */
92 }
93
94
95 static COLR *
96 getpictscan( /* get picture scanline */
97 int y
98 )
99 {
100 register SCAN *sl;
101 register int i;
102 /* first check our buffers */
103 sl = claimscan(y);
104 if (sl == NULL)
105 memerr("claimscan()");
106 sl->lused = ncall++;
107 if (sl->y == y) /* scan hit */
108 return(scandata(sl));
109 /* else read in replacement */
110 if (scanpos[y] < 0) { /* need to search */
111 for (i = y+1; i < curpos; i++)
112 if (scanpos[i] >= 0) {
113 if (fseek(pictfp, scanpos[i], 0) < 0)
114 goto seekerr;
115 curpos = i;
116 break;
117 }
118 while (curpos >= y) {
119 scanpos[curpos] = ftell(pictfp);
120 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
121 goto readerr;
122 nread++;
123 curpos--;
124 }
125 } else {
126 if (curpos != y && fseek(pictfp, scanpos[y], 0) < 0)
127 goto seekerr;
128 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
129 goto readerr;
130 nread++;
131 curpos = y-1;
132 }
133 sl->y = y;
134 i = shash(y); /* add to hash list */
135 sl->next = hashtab[i];
136 hashtab[i] = sl;
137 return(scandata(sl));
138 readerr:
139 fprintf(stderr, "%s: picture read error\n", progname);
140 exit(1);
141 seekerr:
142 fprintf(stderr, "%s: picture seek error\n", progname);
143 exit(1);
144 }
145
146
147 #ifdef DEBUG
148 void
149 pict_stats(void) /* print out picture read statistics */
150 {
151 static long lastcall = 0L; /* ncall at last report */
152 static long lastread = 0L; /* nread at last report */
153 static long lastrecl = 0L; /* nrecl at last report */
154
155 if (ncall == lastcall)
156 return;
157 fprintf(stderr, "%s: %ld scanlines read (%ld reclaimed) in %ld calls\n",
158 progname, nread-lastread, nrecl-lastrecl, ncall-lastcall);
159 lastcall = ncall;
160 lastread = nread;
161 lastrecl = nrecl;
162 }
163 #endif
164
165
166 static double
167 pict_val( /* find picture value for view direction */
168 FVECT vd
169 )
170 {
171 FVECT pp;
172 FVECT ip;
173 COLOR res;
174
175 if (pictfp == NULL)
176 return(-1.0);
177 pp[0] = pictview.vp[0] + vd[0];
178 pp[1] = pictview.vp[1] + vd[1];
179 pp[2] = pictview.vp[2] + vd[2];
180 if (viewloc(ip, &pictview, pp) != 1)
181 return(-1.0);
182 colr_color(res, getpictscan((int)(ip[1]*pysiz))[(int)(ip[0]*pxsiz)]);
183 return(luminance(res)/exposure);
184 }
185
186
187 extern double
188 getviewpix( /* compute single view pixel */
189 int vh,
190 int vv
191 )
192 {
193 FVECT dir;
194 float rt_buf[12];
195 double res;
196
197 if (compdir(dir, vh, vv) < 0)
198 return(-1.0);
199 npixinvw++;
200 if ((res = pict_val(dir)) >= 0.0)
201 return(res);
202 if (rt_pd.r == -1) {
203 npixmiss++;
204 return(-1.0);
205 }
206 rt_buf[0] = ourview.vp[0];
207 rt_buf[1] = ourview.vp[1];
208 rt_buf[2] = ourview.vp[2];
209 rt_buf[3] = dir[0];
210 rt_buf[4] = dir[1];
211 rt_buf[5] = dir[2];
212 rt_compute(rt_buf, 1);
213 return(luminance(rt_buf));
214 }
215
216
217 extern void
218 getviewspan( /* compute a span of view pixels */
219 int vv,
220 float *vb
221 )
222 {
223 float rt_buf[6*MAXPIX]; /* rtrace send/receive buffer */
224 register int n; /* number of pixels in buffer */
225 short buf_vh[MAXPIX]; /* pixel positions */
226 FVECT dir;
227 register int vh;
228
229 #ifdef DEBUG
230 if (verbose)
231 fprintf(stderr, "%s: computing view span at %d...\n",
232 progname, vv);
233 #endif
234 n = 0;
235 for (vh = -hsize; vh <= hsize; vh++) {
236 if (compdir(dir, vh, vv) < 0) { /* not in view */
237 vb[vh+hsize] = -1.0;
238 continue;
239 }
240 npixinvw++;
241 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
242 continue;
243 if (rt_pd.r == -1) { /* missing information */
244 npixmiss++;
245 continue;
246 }
247 /* send to rtrace */
248 if (n >= maxpix) { /* flush */
249 rt_compute(rt_buf, n);
250 while (n > 0) {
251 --n;
252 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
253 }
254 }
255 rt_buf[6*n] = ourview.vp[0];
256 rt_buf[6*n+1] = ourview.vp[1];
257 rt_buf[6*n+2] = ourview.vp[2];
258 rt_buf[6*n+3] = dir[0];
259 rt_buf[6*n+4] = dir[1];
260 rt_buf[6*n+5] = dir[2];
261 buf_vh[n++] = vh;
262 }
263 #ifdef DEBUG
264 if (verbose)
265 pict_stats();
266 #endif
267 if (n > 0) { /* process pending buffer */
268 rt_compute(rt_buf, n);
269 while (n-- > 0)
270 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
271 }
272 }
273
274
275 static void
276 rt_compute( /* process buffer through rtrace */
277 float *pb,
278 int np
279 )
280 {
281 #ifdef DEBUG
282 if (verbose && np > 1)
283 fprintf(stderr, "%s: sending %d samples to rtrace...\n",
284 progname, np);
285 #endif
286 memset(pb+6*np, '\0', 6*sizeof(float));
287 if (process(&rt_pd, (char *)pb, (char *)pb, 3*sizeof(float)*(np+1),
288 6*sizeof(float)*(np+1)) < 3*sizeof(float)*(np+1)) {
289 fprintf(stderr, "%s: rtrace communication error\n",
290 progname);
291 exit(1);
292 }
293 }
294
295
296 static int
297 getexpos( /* get exposure from header line */
298 char *s,
299 void *p
300 )
301 {
302 char fmt[MAXFMTLEN];
303
304 if (isexpos(s))
305 exposure *= exposval(s);
306 else if (isformat(s)) {
307 formatval(fmt, s);
308 wrongformat = strcmp(fmt, COLRFMT);
309 }
310 return(0);
311 }
312
313
314 extern void
315 open_pict( /* open picture file */
316 char *fn
317 )
318 {
319 if ((pictfp = fopen(fn, "r")) == NULL) {
320 fprintf(stderr, "%s: cannot open\n", fn);
321 exit(1);
322 }
323 SET_FILE_BINARY(pictfp);
324 exposure = 1.0;
325 getheader(pictfp, getexpos, NULL);
326 if (wrongformat || !fscnresolu(&pxsiz, &pysiz, pictfp)) {
327 fprintf(stderr, "%s: incompatible picture format\n", fn);
328 exit(1);
329 }
330 initscans();
331 }
332
333
334 extern void
335 close_pict(void) /* done with picture */
336 {
337 if (pictfp == NULL)
338 return;
339 fclose(pictfp);
340 donescans();
341 pictfp = NULL;
342 }
343
344
345 extern void
346 fork_rtrace( /* open pipe and start rtrace */
347 char *av[]
348 )
349 {
350 int rval;
351
352 rval = open_process(&rt_pd, av);
353 if (rval < 0) {
354 perror(progname);
355 exit(1);
356 }
357 if (rval == 0) {
358 fprintf(stderr, "%s: command not found\n", av[0]);
359 exit(1);
360 }
361 maxpix = rval/(6*sizeof(float));
362 if (maxpix > MAXPIX)
363 maxpix = MAXPIX;
364 maxpix--;
365 }
366
367
368 extern void
369 done_rtrace(void) /* wait for rtrace to finish */
370 {
371 int status;
372
373 status = close_process(&rt_pd);
374 if (status > 0) {
375 fprintf(stderr, "%s: bad status (%d) from rtrace\n",
376 progname, status);
377 exit(1);
378 }
379 rt_pd.r = -1;
380 }
381
382
383 static SCAN *
384 scanretire(void) /* retire old scanlines to free list */
385 {
386 SCAN *sold[NRETIRE];
387 int n;
388 int h;
389 register SCAN *sl;
390 register int i;
391 /* grab the NRETIRE oldest scanlines */
392 sold[n = 0] = NULL;
393 for (h = 0; h < HSIZE; h++)
394 for (sl = hashtab[h]; sl != NULL; sl = sl->next) {
395 for (i = n; i && sold[i-1]->lused > sl->lused; i--)
396 if (i < NRETIRE)
397 sold[i] = sold[i-1];
398 if (i < NRETIRE) {
399 sold[i] = sl;
400 if (n < NRETIRE) /* grow list */
401 n++;
402 }
403 }
404 /* put scanlines into free list */
405 for (i = 0; i < n; i++) {
406 h = shash(sold[i]->y);
407 sl = hashtab[h];
408 if (sl == sold[i])
409 hashtab[h] = sl->next;
410 else {
411 while (sl->next != sold[i]) /* IS in list */
412 sl = sl->next;
413 sl->next = sold[i]->next;
414 }
415 if (i > 0) { /* save oldest as return value */
416 sold[i]->next = freelist;
417 freelist = sold[i];
418 }
419 }
420 return(sold[0]);
421 }
422
423
424 static char *scan_buf;
425
426
427 static void
428 initscans(void) /* initialize scanline buffers */
429 {
430 int scansize;
431 register SCAN *ptr;
432 register int i;
433 /* initialize positions */
434 scanpos = (long *)bmalloc(pysiz*sizeof(long));
435 if (scanpos == NULL)
436 memerr("scanline positions");
437 for (i = pysiz-1; i >= 0; i--)
438 scanpos[i] = -1L;
439 curpos = pysiz-1;
440 /* clear hash table */
441 for (i = 0; i < HSIZE; i++)
442 hashtab[i] = NULL;
443 /* allocate scanline buffers */
444 scansize = sizeof(SCAN) + pxsiz*sizeof(COLR);
445 #ifdef ALIGNT
446 scansize = scansize+(sizeof(ALIGNT)-1) & ~(sizeof(ALIGNT)-1);
447 #endif
448 i = MAXSBUF / scansize; /* compute number to allocate */
449 if (i > HSIZE)
450 i = HSIZE;
451 scanbufsiz = i*scansize;
452 scan_buf = bmalloc(scanbufsiz); /* get in one big chunk */
453 if (scan_buf == NULL)
454 memerr("scanline buffers");
455 ptr = (SCAN *)scan_buf;
456 freelist = NULL; /* build our free list */
457 while (i-- > 0) {
458 ptr->y = -1;
459 ptr->lused = -1;
460 ptr->next = freelist;
461 freelist = ptr;
462 ptr = (SCAN *)((char *)ptr + scansize); /* beware of C bugs */
463 }
464 }
465
466
467 static void
468 donescans(void) /* free up scanlines */
469 {
470 bfree(scan_buf, scanbufsiz);
471 bfree((char *)scanpos, pysiz*sizeof(long));
472 }