0023843: scanf without field width limits can crash with huge input data.
[occt.git] / src / Voxel / Voxel_Reader.cxx
1 // Created on: 2008-08-28
2 // Created by: Vladislav ROMASHKO
3 // Copyright (c) 2008-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <Voxel_Reader.ixx>
22 #include <Voxel_BoolDS.hxx>
23 #include <Voxel_ColorDS.hxx>
24 #include <Voxel_FloatDS.hxx>
25 #include <Voxel_VoxelFileFormat.hxx>
26 #include <Voxel_TypeDef.hxx>
27
28 #include <TCollection_AsciiString.hxx>
29
30 Voxel_Reader::Voxel_Reader():myBoolVoxels(0),myColorVoxels(0),myFloatVoxels(0)
31 {
32
33 }
34
35 Standard_Boolean Voxel_Reader::Read(const TCollection_ExtendedString& file)
36 {
37   // Open file in ASCII mode to read header
38   FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "r");
39   if (!f)
40     return Standard_False;
41
42   // Read the header
43   Standard_Byte type; // 0 - bool, 1 - color, 2 - float
44   Voxel_VoxelFileFormat format;
45   Standard_Character svoxels[9], sformat[9], stype[9];
46   fscanf(f, "%8s %8s %8s\n", svoxels, sformat, stype);
47   fclose(f);
48
49   // Take format, type of voxels.
50   // Voxels
51   if (strcmp(svoxels, VOXELS))
52     return Standard_False;
53   // Format
54   if (strcmp(sformat, ASCII) == 0)
55     format = Voxel_VFF_ASCII;
56   else if (strcmp(sformat, BINARY) == 0)
57     format = Voxel_VFF_BINARY;
58   else
59     return Standard_False;
60   // Type of voxels
61   if (strcmp(stype, BOOL) == 0)
62     type = 0;
63   else if (strcmp(stype, COLOR) == 0)
64     type = 1;
65   else if (strcmp(stype, FLOAT) == 0)
66     type = 2;
67   else
68     return Standard_False;
69
70   // Read the rest
71   switch (format)
72   {
73     case Voxel_VFF_ASCII:
74     {
75       switch (type)
76       {
77         case 0:
78           return ReadBoolAsciiVoxels(file);
79         case 1:
80           return ReadColorAsciiVoxels(file);
81         case 2:
82           return ReadFloatAsciiVoxels(file);
83       }
84     }
85     case Voxel_VFF_BINARY:
86     {
87       switch (type)
88       {
89         case 0:
90           return ReadBoolBinaryVoxels(file);
91         case 1:
92           return ReadColorBinaryVoxels(file);
93         case 2:
94           return ReadFloatBinaryVoxels(file);
95       }
96     }
97   }
98
99   // No voxels or no format description is found:
100   return Standard_False;
101 }
102
103 Standard_Boolean Voxel_Reader::IsBoolVoxels() const
104 {
105   return (myBoolVoxels != 0);
106 }
107
108 Standard_Boolean Voxel_Reader::IsColorVoxels() const
109 {
110   return (myColorVoxels != 0);
111 }
112
113 Standard_Boolean Voxel_Reader::IsFloatVoxels() const
114 {
115   return (myFloatVoxels != 0);
116 }
117
118 Standard_Address Voxel_Reader::GetBoolVoxels() const
119 {
120   return myBoolVoxels;
121 }
122
123 Standard_Address Voxel_Reader::GetColorVoxels() const
124 {
125   return myColorVoxels;
126 }
127
128 Standard_Address Voxel_Reader::GetFloatVoxels() const
129 {
130   return myFloatVoxels;
131 }
132
133 static Standard_Boolean has_slice(const Standard_CString line)
134 {
135   Standard_Integer i = 0, nb_spaces = 0;
136   while (line[i] != '\0')
137   {
138     if (line[i] == ' ')
139       nb_spaces++;
140     i++;
141   }
142   return (nb_spaces == 2);
143 }
144
145 Standard_Boolean Voxel_Reader::ReadBoolAsciiVoxels(const TCollection_ExtendedString& file)
146 {
147   // Open file for reading
148   FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "r");
149   if (!f)
150     return Standard_False;
151   Standard_Character line[65], sx[33], sy[33], sz[33];
152
153   // Header: skip it
154   fgets(line, 64, f);
155   
156   // Location, size, number of splits
157   Standard_Integer nbx = 0, nby = 0, nbz = 0;
158   Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
159   if (fscanf(f, "%32s %32s %32s\n", sx, sy, sz) != 3)
160   {
161     fclose(f);
162     return Standard_False;
163   }
164   x = Atof(sx); y = Atof(sy); z = Atof(sz);
165   if (fscanf(f, "%32s %32s %32s\n", sx, sy, sz) != 3)
166   {
167     fclose(f);
168     return Standard_False;
169   }
170   xlen = Atof(sx); ylen = Atof(sy); zlen = Atof(sz);
171   if (fscanf(f, "%d %d %d\n", &nbx, &nby, &nbz) != 3)
172   {
173     fclose(f);
174     return Standard_False;
175   }
176
177   // Allocate the voxels
178   myBoolVoxels = (Standard_Address) new Voxel_BoolDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
179
180   // Data
181   // Copied from Voxel_BoolDS.cxx:
182   Standard_Integer nb_bytes = RealToInt(ceil(nbx * nby * nbz / 8.0));
183   Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 8.0));
184   // myData[0 .. nb_slices - 1][0 .. 7]
185   if (nb_slices)
186   {
187     Standard_Integer i1 = 0, i2 = 0, value = 0;
188     while (!feof(f))
189     {
190       fgets(line, 64, f);
191       if (has_slice(line))
192       {
193         if (sscanf(line, "%d %d %d\n", &i1, &i2, &value) != 3)
194         {
195           fclose(f);
196           return Standard_False;
197         }
198       }
199       else
200       {
201         if (sscanf(line, "%d %d\n", &i2, &value) != 2)
202         {
203           fclose(f);
204           return Standard_False;
205         }
206       }
207
208       // Set value
209       if (!((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1])
210       {
211         ((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1] = 
212           (Standard_Byte*) calloc(8/*number of bytes in slice*/, sizeof(Standard_Byte));
213       }
214       (((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1])[i2] = value;
215     }
216   }
217
218   fclose(f);
219   return Standard_True;
220 }
221
222 Standard_Boolean Voxel_Reader::ReadColorAsciiVoxels(const TCollection_ExtendedString& file)
223 {
224   // Open file for reading
225   FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "r");
226   if (!f)
227     return Standard_False;
228   Standard_Character line[65], sx[33], sy[33], sz[33];
229
230   // Header: skip it
231   fgets(line, 64, f);
232   
233   // Location, size, number of splits
234   Standard_Integer nbx = 0, nby = 0, nbz = 0;
235   Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
236   if (fscanf(f, "%32s %32s %32s\n", sx, sy, sz) != 3)
237   {
238     fclose(f);
239     return Standard_False;
240   }
241   x = Atof(sx); y = Atof(sy); z = Atof(sz);
242   if (fscanf(f, "%32s %32s %32s\n", sx, sy, sz) != 3)
243   {
244     fclose(f);
245     return Standard_False;
246   }
247   xlen = Atof(sx); ylen = Atof(sy); zlen = Atof(sz);
248   if (fscanf(f, "%d %d %d\n", &nbx, &nby, &nbz) != 3)
249   {
250     fclose(f);
251     return Standard_False;
252   }
253
254   // Allocate the voxels
255   myColorVoxels = (Standard_Address) new Voxel_ColorDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
256
257   // Data
258   // Copied from Voxel_ColorDS.cxx:
259   Standard_Integer nb_bytes = RealToInt(ceil(nbx * nby * nbz / 2.0));
260   Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 32.0));
261   // myData[0 .. nb_slices - 1][0 .. 31]
262   if (nb_slices)
263   {
264     Standard_Integer i1 = 0, i2 = 0, value = 0;
265     while (!feof(f))
266     {
267       fgets(line, 64, f);
268       if (has_slice(line))
269       {
270         if (sscanf(line, "%d %d %d\n", &i1, &i2, &value) != 3)
271         {
272           fclose(f);
273           return Standard_False;
274         }
275       }
276       else
277       {
278         if (sscanf(line, "%d %d\n", &i2, &value) != 2)
279         {
280           fclose(f);
281           return Standard_False;
282         }
283       }
284
285       // Set value
286       if (!((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1])
287       {
288         ((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1] = 
289           (Standard_Byte*) calloc(32/*number of bytes in slice*/, sizeof(Standard_Byte));
290       }
291       (((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1])[i2] = value;
292     }
293   }
294
295   fclose(f);
296   return Standard_True;
297 }
298
299 Standard_Boolean Voxel_Reader::ReadFloatAsciiVoxels(const TCollection_ExtendedString& file)
300 {
301   // Open file for reading
302   FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "r");
303   if (!f)
304     return Standard_False;
305   Standard_Character line[65], sx[33], sy[33], sz[33];
306
307   // Header: skip it
308   fgets(line, 64, f);
309   
310   // Location, size, number of splits
311   Standard_Integer nbx = 0, nby = 0, nbz = 0;
312   Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
313   if (fscanf(f, "%32s %32s %32s\n", sx, sy, sz) != 3)
314   {
315     fclose(f);
316     return Standard_False;
317   }
318   x = Atof(sx); y = Atof(sy); z = Atof(sz);
319   if (fscanf(f, "%32s %32s %32s\n", sx, sy, sz) != 3)
320   {
321     fclose(f);
322     return Standard_False;
323   }
324   xlen = Atof(sx); ylen = Atof(sy); zlen = Atof(sz);
325   if (fscanf(f, "%d %d %d\n", &nbx, &nby, &nbz) != 3)
326   {
327     fclose(f);
328     return Standard_False;
329   }
330
331   // Allocate the voxels
332   myFloatVoxels = (Standard_Address) new Voxel_FloatDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
333
334   // Data
335   // Copied from Voxel_FloatDS.cxx:
336   Standard_Integer nb_floats = nbx * nby * nbz;
337   Standard_Integer nb_slices = RealToInt(ceil(nb_floats / 32.0)); // 32 values in 1 slice
338   // myData[0 .. nb_slices - 1][0 .. 31]
339   if (nb_slices)
340   {
341     Standard_Integer i1 = 0, i2 = 0;
342     Standard_ShortReal value = 0.0;
343     while (!feof(f))
344     {
345       fgets(line, 64, f);
346       if (has_slice(line))
347       {
348         if (sscanf(line, "%d %d %64s\n", &i1, &i2, line) != 3)
349         {
350           fclose(f);
351           return Standard_False;
352         }
353       }
354       else
355       {
356         if (sscanf(line, "%d %64s\n", &i2, line) != 2)
357         {
358           fclose(f);
359           return Standard_False;
360         }
361       }
362       value = (Standard_ShortReal)Atof(line);
363
364       // Set value
365       if (!((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1])
366       {
367         ((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1] = 
368           (Standard_ShortReal*) calloc(32/*number of floats in slice*/, sizeof(Standard_ShortReal));
369       }
370       (((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1])[i2] = value;
371     }
372   }
373
374   fclose(f);
375   return Standard_True;
376 }
377
378 Standard_Boolean Voxel_Reader::ReadBoolBinaryVoxels(const TCollection_ExtendedString& file)
379 {
380   // Open file for reading
381   FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "rb");
382   if (!f)
383     return Standard_False;
384
385   // Header: skip it
386   Standard_Character line[65];
387   fgets(line, 64, f);
388   
389   // Location, size, number of splits
390   Standard_Integer nbx = 0, nby = 0, nbz = 0;
391   Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
392   fread(&x, sizeof(Standard_Real), 1, f);
393   fread(&y, sizeof(Standard_Real), 1, f);
394   fread(&z, sizeof(Standard_Real), 1, f);
395   fread(&xlen, sizeof(Standard_Real), 1, f);
396   fread(&ylen, sizeof(Standard_Real), 1, f);
397   fread(&zlen, sizeof(Standard_Real), 1, f);
398   fread(&nbx, sizeof(Standard_Integer), 1, f);
399   fread(&nby, sizeof(Standard_Integer), 1, f);
400   fread(&nbz, sizeof(Standard_Integer), 1, f);
401
402   // Allocate the voxels
403   myBoolVoxels = (Standard_Address) new Voxel_BoolDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
404
405   // Data
406   // Copied from Voxel_BoolDS.cxx:
407   Standard_Integer nb_bytes = RealToInt(ceil(nbx * nby * nbz / 8.0));
408   Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 8.0));
409   // myData[0 .. nb_slices - 1][0 .. 7]
410   if (nb_slices)
411   {
412     Standard_Integer i1 = 0, i2 = 0, value = 0;
413     while (!feof(f))
414     {
415       fread(&i1, sizeof(Standard_Integer), 1, f);
416       fread(&i2, sizeof(Standard_Integer), 1, f);
417       fread(&value, sizeof(Standard_Byte), 1, f);
418
419       // Set value
420       if (!((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1])
421       {
422         ((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1] = 
423           (Standard_Byte*) calloc(8/*number of bytes in slice*/, sizeof(Standard_Byte));
424       }
425       (((Standard_Byte**)((Voxel_DS*)myBoolVoxels)->myData)[i1])[i2] = value;
426     }
427   }
428
429   fclose(f);
430   return Standard_True;
431 }
432
433 Standard_Boolean Voxel_Reader::ReadColorBinaryVoxels(const TCollection_ExtendedString& file)
434 {
435   // Open file for reading
436   FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "rb");
437   if (!f)
438     return Standard_False;
439
440   // Header: skip it
441   Standard_Character line[65];
442   fgets(line, 64, f);
443   
444   // Location, size, number of splits
445   Standard_Integer nbx = 0, nby = 0, nbz = 0;
446   Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
447   fread(&x, sizeof(Standard_Real), 1, f);
448   fread(&y, sizeof(Standard_Real), 1, f);
449   fread(&z, sizeof(Standard_Real), 1, f);
450   fread(&xlen, sizeof(Standard_Real), 1, f);
451   fread(&ylen, sizeof(Standard_Real), 1, f);
452   fread(&zlen, sizeof(Standard_Real), 1, f);
453   fread(&nbx, sizeof(Standard_Integer), 1, f);
454   fread(&nby, sizeof(Standard_Integer), 1, f);
455   fread(&nbz, sizeof(Standard_Integer), 1, f);
456
457   // Allocate the voxels
458   myColorVoxels = (Standard_Address) new Voxel_ColorDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
459
460   // Data
461   // Copied from Voxel_ColorDS.cxx:
462   Standard_Integer nb_bytes = RealToInt(ceil(nbx * nby * nbz / 2.0));
463   Standard_Integer nb_slices = RealToInt(ceil(nb_bytes / 32.0));
464   // myData[0 .. nb_slices - 1][0 .. 31]
465   if (nb_slices)
466   {
467     Standard_Integer i1 = 0, i2 = 0, value = 0;
468     while (!feof(f))
469     {
470       fread(&i1, sizeof(Standard_Integer), 1, f);
471       fread(&i2, sizeof(Standard_Integer), 1, f);
472       fread(&value, sizeof(Standard_Byte), 1, f);
473
474       // Set value
475       if (!((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1])
476       {
477         ((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1] = 
478           (Standard_Byte*) calloc(32/*number of bytes in slice*/, sizeof(Standard_Byte));
479       }
480       (((Standard_Byte**)((Voxel_DS*)myColorVoxels)->myData)[i1])[i2] = value;
481     }
482   }
483
484   fclose(f);
485   return Standard_True;
486 }
487
488 Standard_Boolean Voxel_Reader::ReadFloatBinaryVoxels(const TCollection_ExtendedString& file)
489 {
490   // Open file for reading
491   FILE* f = fopen(TCollection_AsciiString(file, '?').ToCString(), "rb");
492   if (!f)
493     return Standard_False;
494
495   // Header: skip it
496   Standard_Character line[65];
497   fgets(line, 64, f);
498   
499   // Location, size, number of splits
500   Standard_Integer nbx = 0, nby = 0, nbz = 0;
501   Standard_Real x = 0.0, y = 0.0, z = 0.0, xlen = 0.0, ylen = 0.0, zlen = 0.0;
502   fread(&x, sizeof(Standard_Real), 1, f);
503   fread(&y, sizeof(Standard_Real), 1, f);
504   fread(&z, sizeof(Standard_Real), 1, f);
505   fread(&xlen, sizeof(Standard_Real), 1, f);
506   fread(&ylen, sizeof(Standard_Real), 1, f);
507   fread(&zlen, sizeof(Standard_Real), 1, f);
508   fread(&nbx, sizeof(Standard_Integer), 1, f);
509   fread(&nby, sizeof(Standard_Integer), 1, f);
510   fread(&nbz, sizeof(Standard_Integer), 1, f);
511
512   // Allocate the voxels
513   myFloatVoxels = (Standard_Address) new Voxel_FloatDS(x, y, z, xlen, ylen, zlen, nbx, nby, nbz);
514
515   // Data
516   // Copied from Voxel_FloatDS.cxx:
517   Standard_Integer nb_floats = nbx * nby * nbz;
518   Standard_Integer nb_slices = RealToInt(ceil(nb_floats / 32.0)); // 32 values in 1 slice
519   // myData[0 .. nb_slices - 1][0 .. 31]
520   if (nb_slices)
521   {
522     Standard_Integer i1 = 0, i2 = 0;
523     Standard_ShortReal value = 0.0;
524     while (!feof(f))
525     {
526       fread(&i1, sizeof(Standard_Integer), 1, f);
527       fread(&i2, sizeof(Standard_Integer), 1, f);
528       fread(&value, sizeof(Standard_ShortReal), 1, f);
529
530       // Set value
531       if (!((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1])
532       {
533         ((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1] = 
534           (Standard_ShortReal*) calloc(32/*number of floats in slice*/, sizeof(Standard_ShortReal));
535       }
536       (((Standard_ShortReal**)((Voxel_DS*)myFloatVoxels)->myData)[i1])[i2] = value;
537     }
538   }
539
540   fclose(f);
541   return Standard_True;
542 }