don't crash in ReadString() if the length read from the stream is too big (bug 1933560)
[wxWidgets.git] / src / common / datstrm.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/datstrm.cpp
3 // Purpose: Data stream classes
4 // Author: Guilhem Lavaux
5 // Modified by: Mickael Gilabert
6 // Created: 28/06/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Guilhem Lavaux
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_STREAMS
20
21 #include "wx/datstrm.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/math.h"
25 #endif //WX_PRECOMP
26
27 // ---------------------------------------------------------------------------
28 // wxDataInputStream
29 // ---------------------------------------------------------------------------
30
31 #if wxUSE_UNICODE
32 wxDataInputStream::wxDataInputStream(wxInputStream& s, const wxMBConv& conv)
33 : m_input(&s), m_be_order(false), m_conv(conv.Clone())
34 #else
35 wxDataInputStream::wxDataInputStream(wxInputStream& s)
36 : m_input(&s), m_be_order(false)
37 #endif
38 {
39 }
40
41 wxDataInputStream::~wxDataInputStream()
42 {
43 #if wxUSE_UNICODE
44 delete m_conv;
45 #endif // wxUSE_UNICODE
46 }
47
48 #if wxHAS_INT64
49 wxUint64 wxDataInputStream::Read64()
50 {
51 wxUint64 tmp;
52 Read64(&tmp, 1);
53 return tmp;
54 }
55 #endif // wxHAS_INT64
56
57 wxUint32 wxDataInputStream::Read32()
58 {
59 wxUint32 i32;
60
61 m_input->Read(&i32, 4);
62
63 if (m_be_order)
64 return wxUINT32_SWAP_ON_LE(i32);
65 else
66 return wxUINT32_SWAP_ON_BE(i32);
67 }
68
69 wxUint16 wxDataInputStream::Read16()
70 {
71 wxUint16 i16;
72
73 m_input->Read(&i16, 2);
74
75 if (m_be_order)
76 return wxUINT16_SWAP_ON_LE(i16);
77 else
78 return wxUINT16_SWAP_ON_BE(i16);
79 }
80
81 wxUint8 wxDataInputStream::Read8()
82 {
83 wxUint8 buf;
84
85 m_input->Read(&buf, 1);
86 return (wxUint8)buf;
87 }
88
89 double wxDataInputStream::ReadDouble()
90 {
91 #if wxUSE_APPLE_IEEE
92 char buf[10];
93
94 m_input->Read(buf, 10);
95 return wxConvertFromIeeeExtended((const wxInt8 *)buf);
96 #else
97 return 0.0;
98 #endif
99 }
100
101 wxString wxDataInputStream::ReadString()
102 {
103 wxString ret;
104
105 const size_t len = Read32();
106 if ( len > 0 )
107 {
108 #if wxUSE_UNICODE
109 wxCharBuffer tmp(len + 1);
110 if ( tmp )
111 {
112 m_input->Read(tmp.data(), len);
113 tmp.data()[len] = '\0';
114 ret = m_conv->cMB2WX(tmp.data());
115 }
116 #else
117 wxStringBuffer buf(ret, len);
118 if ( buf )
119 m_input->Read(buf, len);
120 #endif
121 }
122
123 return ret;
124 }
125
126 #if wxUSE_LONGLONG
127
128 template <class T>
129 static
130 void DoReadLL(T *buffer, size_t size, wxInputStream *input, bool be_order)
131 {
132 typedef T DataType;
133 unsigned char *pchBuffer = new unsigned char[size * 8];
134 // TODO: Check for overflow when size is of type uint and is > than 512m
135 input->Read(pchBuffer, size * 8);
136 size_t idx_base = 0;
137 if ( be_order )
138 {
139 for ( size_t uiIndex = 0; uiIndex != size; ++uiIndex )
140 {
141 buffer[uiIndex] = 0l;
142 for ( unsigned ui = 0; ui != 8; ++ui )
143 {
144 buffer[uiIndex] = buffer[uiIndex] * 256l +
145 DataType((unsigned long) pchBuffer[idx_base + ui]);
146 }
147
148 idx_base += 8;
149 }
150 }
151 else // little endian
152 {
153 for ( size_t uiIndex=0; uiIndex!=size; ++uiIndex )
154 {
155 buffer[uiIndex] = 0l;
156 for ( unsigned ui=0; ui!=8; ++ui )
157 buffer[uiIndex] = buffer[uiIndex] * 256l +
158 DataType((unsigned long) pchBuffer[idx_base + 7 - ui]);
159 idx_base += 8;
160 }
161 }
162 delete[] pchBuffer;
163 }
164
165 template <class T>
166 static void DoWriteLL(const T *buffer, size_t size, wxOutputStream *output, bool be_order)
167 {
168 typedef T DataType;
169 unsigned char *pchBuffer = new unsigned char[size * 8];
170 size_t idx_base = 0;
171 if ( be_order )
172 {
173 for ( size_t uiIndex = 0; uiIndex != size; ++uiIndex )
174 {
175 DataType i64 = buffer[uiIndex];
176 for ( unsigned ui = 0; ui != 8; ++ui )
177 {
178 pchBuffer[idx_base + 7 - ui] =
179 (unsigned char) (i64.GetLo() & 255l);
180 i64 >>= 8l;
181 }
182
183 idx_base += 8;
184 }
185 }
186 else // little endian
187 {
188 for ( size_t uiIndex=0; uiIndex != size; ++uiIndex )
189 {
190 DataType i64 = buffer[uiIndex];
191 for (unsigned ui=0; ui!=8; ++ui)
192 {
193 pchBuffer[idx_base + ui] =
194 (unsigned char) (i64.GetLo() & 255l);
195 i64 >>= 8l;
196 }
197
198 idx_base += 8;
199 }
200 }
201
202 // TODO: Check for overflow when size is of type uint and is > than 512m
203 output->Write(pchBuffer, size * 8);
204 delete[] pchBuffer;
205 }
206
207 #endif // wxUSE_LONGLONG
208
209 #ifdef wxLongLong_t
210
211 template <class T>
212 static
213 void DoReadI64(T *buffer, size_t size, wxInputStream *input, bool be_order)
214 {
215 typedef T DataType;
216 unsigned char *pchBuffer = (unsigned char*) buffer;
217 // TODO: Check for overflow when size is of type uint and is > than 512m
218 input->Read(pchBuffer, size * 8);
219 if ( be_order )
220 {
221 for ( wxUint32 i = 0; i < size; i++ )
222 {
223 DataType v = wxUINT64_SWAP_ON_LE(*buffer);
224 *(buffer++) = v;
225 }
226 }
227 else // little endian
228 {
229 for ( wxUint32 i=0; i<size; i++ )
230 {
231 DataType v = wxUINT64_SWAP_ON_BE(*buffer);
232 *(buffer++) = v;
233 }
234 }
235 }
236
237 template <class T>
238 static
239 void DoWriteI64(const T *buffer, size_t size, wxOutputStream *output, bool be_order)
240 {
241 typedef T DataType;
242 if ( be_order )
243 {
244 for ( size_t i = 0; i < size; i++ )
245 {
246 DataType i64 = wxUINT64_SWAP_ON_LE(*buffer);
247 buffer++;
248 output->Write(&i64, 8);
249 }
250 }
251 else // little endian
252 {
253 for ( size_t i=0; i < size; i++ )
254 {
255 DataType i64 = wxUINT64_SWAP_ON_BE(*buffer);
256 buffer++;
257 output->Write(&i64, 8);
258 }
259 }
260 }
261
262 #endif // wxLongLong_t
263
264
265 #if wxHAS_INT64
266 void wxDataInputStream::Read64(wxUint64 *buffer, size_t size)
267 {
268 #ifndef wxLongLong_t
269 DoReadLL(buffer, size, m_input, m_be_order);
270 #else
271 DoReadI64(buffer, size, m_input, m_be_order);
272 #endif
273 }
274
275 void wxDataInputStream::Read64(wxInt64 *buffer, size_t size)
276 {
277 #ifndef wxLongLong_t
278 DoReadLL(buffer, size, m_input, m_be_order);
279 #else
280 DoReadI64(buffer, size, m_input, m_be_order);
281 #endif
282 }
283 #endif // wxHAS_INT64
284
285 #if defined(wxLongLong_t) && wxUSE_LONGLONG
286 void wxDataInputStream::Read64(wxULongLong *buffer, size_t size)
287 {
288 DoReadLL(buffer, size, m_input, m_be_order);
289 }
290
291 void wxDataInputStream::Read64(wxLongLong *buffer, size_t size)
292 {
293 DoReadLL(buffer, size, m_input, m_be_order);
294 }
295 #endif // wxLongLong_t
296
297 #if wxUSE_LONGLONG
298 void wxDataInputStream::ReadLL(wxULongLong *buffer, size_t size)
299 {
300 DoReadLL(buffer, size, m_input, m_be_order);
301 }
302
303 void wxDataInputStream::ReadLL(wxLongLong *buffer, size_t size)
304 {
305 DoReadLL(buffer, size, m_input, m_be_order);
306 }
307
308 wxLongLong wxDataInputStream::ReadLL(void)
309 {
310 wxLongLong ll;
311 DoReadLL(&ll, (size_t)1, m_input, m_be_order);
312 return ll;
313 }
314 #endif // wxUSE_LONGLONG
315
316 void wxDataInputStream::Read32(wxUint32 *buffer, size_t size)
317 {
318 m_input->Read(buffer, size * 4);
319
320 if (m_be_order)
321 {
322 for (wxUint32 i=0; i<size; i++)
323 {
324 wxUint32 v = wxUINT32_SWAP_ON_LE(*buffer);
325 *(buffer++) = v;
326 }
327 }
328 else
329 {
330 for (wxUint32 i=0; i<size; i++)
331 {
332 wxUint32 v = wxUINT32_SWAP_ON_BE(*buffer);
333 *(buffer++) = v;
334 }
335 }
336 }
337
338 void wxDataInputStream::Read16(wxUint16 *buffer, size_t size)
339 {
340 m_input->Read(buffer, size * 2);
341
342 if (m_be_order)
343 {
344 for (wxUint32 i=0; i<size; i++)
345 {
346 wxUint16 v = wxUINT16_SWAP_ON_LE(*buffer);
347 *(buffer++) = v;
348 }
349 }
350 else
351 {
352 for (wxUint32 i=0; i<size; i++)
353 {
354 wxUint16 v = wxUINT16_SWAP_ON_BE(*buffer);
355 *(buffer++) = v;
356 }
357 }
358 }
359
360 void wxDataInputStream::Read8(wxUint8 *buffer, size_t size)
361 {
362 m_input->Read(buffer, size);
363 }
364
365 void wxDataInputStream::ReadDouble(double *buffer, size_t size)
366 {
367 for (wxUint32 i=0; i<size; i++)
368 {
369 *(buffer++) = ReadDouble();
370 }
371 }
372
373 wxDataInputStream& wxDataInputStream::operator>>(wxString& s)
374 {
375 s = ReadString();
376 return *this;
377 }
378
379 wxDataInputStream& wxDataInputStream::operator>>(wxInt8& c)
380 {
381 c = (wxInt8)Read8();
382 return *this;
383 }
384
385 wxDataInputStream& wxDataInputStream::operator>>(wxInt16& i)
386 {
387 i = (wxInt16)Read16();
388 return *this;
389 }
390
391 wxDataInputStream& wxDataInputStream::operator>>(wxInt32& i)
392 {
393 i = (wxInt32)Read32();
394 return *this;
395 }
396
397 wxDataInputStream& wxDataInputStream::operator>>(wxUint8& c)
398 {
399 c = Read8();
400 return *this;
401 }
402
403 wxDataInputStream& wxDataInputStream::operator>>(wxUint16& i)
404 {
405 i = Read16();
406 return *this;
407 }
408
409 wxDataInputStream& wxDataInputStream::operator>>(wxUint32& i)
410 {
411 i = Read32();
412 return *this;
413 }
414
415 #if wxHAS_INT64
416 wxDataInputStream& wxDataInputStream::operator>>(wxUint64& i)
417 {
418 i = Read64();
419 return *this;
420 }
421
422 wxDataInputStream& wxDataInputStream::operator>>(wxInt64& i)
423 {
424 i = Read64();
425 return *this;
426 }
427 #endif // wxHAS_INT64
428
429 #if defined(wxLongLong_t) && wxUSE_LONGLONG
430 wxDataInputStream& wxDataInputStream::operator>>(wxULongLong& i)
431 {
432 i = ReadLL();
433 return *this;
434 }
435
436 wxDataInputStream& wxDataInputStream::operator>>(wxLongLong& i)
437 {
438 i = ReadLL();
439 return *this;
440 }
441 #endif // wxLongLong_t
442
443 wxDataInputStream& wxDataInputStream::operator>>(double& i)
444 {
445 i = ReadDouble();
446 return *this;
447 }
448
449 wxDataInputStream& wxDataInputStream::operator>>(float& f)
450 {
451 f = (float)ReadDouble();
452 return *this;
453 }
454
455 // ---------------------------------------------------------------------------
456 // wxDataOutputStream
457 // ---------------------------------------------------------------------------
458
459 #if wxUSE_UNICODE
460 wxDataOutputStream::wxDataOutputStream(wxOutputStream& s, const wxMBConv& conv)
461 : m_output(&s), m_be_order(false), m_conv(conv.Clone())
462 #else
463 wxDataOutputStream::wxDataOutputStream(wxOutputStream& s)
464 : m_output(&s), m_be_order(false)
465 #endif
466 {
467 }
468
469 wxDataOutputStream::~wxDataOutputStream()
470 {
471 #if wxUSE_UNICODE
472 delete m_conv;
473 #endif // wxUSE_UNICODE
474 }
475
476 #if wxHAS_INT64
477 void wxDataOutputStream::Write64(wxUint64 i)
478 {
479 Write64(&i, 1);
480 }
481
482 void wxDataOutputStream::Write64(wxInt64 i)
483 {
484 Write64(&i, 1);
485 }
486 #endif // wxHAS_INT64
487
488 void wxDataOutputStream::Write32(wxUint32 i)
489 {
490 wxUint32 i32;
491
492 if (m_be_order)
493 i32 = wxUINT32_SWAP_ON_LE(i);
494 else
495 i32 = wxUINT32_SWAP_ON_BE(i);
496 m_output->Write(&i32, 4);
497 }
498
499 void wxDataOutputStream::Write16(wxUint16 i)
500 {
501 wxUint16 i16;
502
503 if (m_be_order)
504 i16 = wxUINT16_SWAP_ON_LE(i);
505 else
506 i16 = wxUINT16_SWAP_ON_BE(i);
507
508 m_output->Write(&i16, 2);
509 }
510
511 void wxDataOutputStream::Write8(wxUint8 i)
512 {
513 m_output->Write(&i, 1);
514 }
515
516 void wxDataOutputStream::WriteString(const wxString& string)
517 {
518 #if wxUSE_UNICODE
519 const wxWX2MBbuf buf = string.mb_str(*m_conv);
520 #else
521 const wxWX2MBbuf buf = string.mb_str();
522 #endif
523 size_t len = strlen(buf);
524 Write32(len);
525 if (len > 0)
526 m_output->Write(buf, len);
527 }
528
529 void wxDataOutputStream::WriteDouble(double d)
530 {
531 char buf[10];
532
533 #if wxUSE_APPLE_IEEE
534 wxConvertToIeeeExtended(d, (wxInt8 *)buf);
535 #else
536 #if !defined(__VMS__) && !defined(__GNUG__)
537 # pragma warning "wxDataOutputStream::WriteDouble() not using IeeeExtended - will not work!"
538 #endif
539 buf[0] = '\0';
540 #endif
541 m_output->Write(buf, 10);
542 }
543
544 #if wxHAS_INT64
545 void wxDataOutputStream::Write64(const wxUint64 *buffer, size_t size)
546 {
547 #ifndef wxLongLong_t
548 DoWriteLL(buffer, size, m_output, m_be_order);
549 #else
550 DoWriteI64(buffer, size, m_output, m_be_order);
551 #endif
552 }
553
554 void wxDataOutputStream::Write64(const wxInt64 *buffer, size_t size)
555 {
556 #ifndef wxLongLong_t
557 DoWriteLL(buffer, size, m_output, m_be_order);
558 #else
559 DoWriteI64(buffer, size, m_output, m_be_order);
560 #endif
561 }
562 #endif // wxHAS_INT64
563
564 #if defined(wxLongLong_t) && wxUSE_LONGLONG
565 void wxDataOutputStream::Write64(const wxULongLong *buffer, size_t size)
566 {
567 DoWriteLL(buffer, size, m_output, m_be_order);
568 }
569
570 void wxDataOutputStream::Write64(const wxLongLong *buffer, size_t size)
571 {
572 DoWriteLL(buffer, size, m_output, m_be_order);
573 }
574 #endif // wxLongLong_t
575
576 #if wxUSE_LONGLONG
577 void wxDataOutputStream::WriteLL(const wxULongLong *buffer, size_t size)
578 {
579 DoWriteLL(buffer, size, m_output, m_be_order);
580 }
581
582 void wxDataOutputStream::WriteLL(const wxLongLong *buffer, size_t size)
583 {
584 DoWriteLL(buffer, size, m_output, m_be_order);
585 }
586
587 void wxDataOutputStream::WriteLL(const wxLongLong &ll)
588 {
589 WriteLL(&ll, 1);
590 }
591
592 void wxDataOutputStream::WriteLL(const wxULongLong &ll)
593 {
594 WriteLL(&ll, 1);
595 }
596 #endif // wxUSE_LONGLONG
597
598 void wxDataOutputStream::Write32(const wxUint32 *buffer, size_t size)
599 {
600 if (m_be_order)
601 {
602 for (wxUint32 i=0; i<size ;i++)
603 {
604 wxUint32 i32 = wxUINT32_SWAP_ON_LE(*buffer);
605 buffer++;
606 m_output->Write(&i32, 4);
607 }
608 }
609 else
610 {
611 for (wxUint32 i=0; i<size ;i++)
612 {
613 wxUint32 i32 = wxUINT32_SWAP_ON_BE(*buffer);
614 buffer++;
615 m_output->Write(&i32, 4);
616 }
617 }
618 }
619
620 void wxDataOutputStream::Write16(const wxUint16 *buffer, size_t size)
621 {
622 if (m_be_order)
623 {
624 for (wxUint32 i=0; i<size ;i++)
625 {
626 wxUint16 i16 = wxUINT16_SWAP_ON_LE(*buffer);
627 buffer++;
628 m_output->Write(&i16, 2);
629 }
630 }
631 else
632 {
633 for (wxUint32 i=0; i<size ;i++)
634 {
635 wxUint16 i16 = wxUINT16_SWAP_ON_BE(*buffer);
636 buffer++;
637 m_output->Write(&i16, 2);
638 }
639 }
640 }
641
642 void wxDataOutputStream::Write8(const wxUint8 *buffer, size_t size)
643 {
644 m_output->Write(buffer, size);
645 }
646
647 void wxDataOutputStream::WriteDouble(const double *buffer, size_t size)
648 {
649 for (wxUint32 i=0; i<size; i++)
650 {
651 WriteDouble(*(buffer++));
652 }
653 }
654
655 wxDataOutputStream& wxDataOutputStream::operator<<(const wxString& string)
656 {
657 WriteString(string);
658 return *this;
659 }
660
661 wxDataOutputStream& wxDataOutputStream::operator<<(wxInt8 c)
662 {
663 Write8((wxUint8)c);
664 return *this;
665 }
666
667 wxDataOutputStream& wxDataOutputStream::operator<<(wxInt16 i)
668 {
669 Write16((wxUint16)i);
670 return *this;
671 }
672
673 wxDataOutputStream& wxDataOutputStream::operator<<(wxInt32 i)
674 {
675 Write32((wxUint32)i);
676 return *this;
677 }
678
679 wxDataOutputStream& wxDataOutputStream::operator<<(wxUint8 c)
680 {
681 Write8(c);
682 return *this;
683 }
684
685 wxDataOutputStream& wxDataOutputStream::operator<<(wxUint16 i)
686 {
687 Write16(i);
688 return *this;
689 }
690
691 wxDataOutputStream& wxDataOutputStream::operator<<(wxUint32 i)
692 {
693 Write32(i);
694 return *this;
695 }
696
697 #if wxHAS_INT64
698 wxDataOutputStream& wxDataOutputStream::operator<<(wxUint64 i)
699 {
700 Write64(i);
701 return *this;
702 }
703
704 wxDataOutputStream& wxDataOutputStream::operator<<(wxInt64 i)
705 {
706 Write64(i);
707 return *this;
708 }
709 #endif // wxHAS_INT64
710
711 #if defined(wxLongLong_t) && wxUSE_LONGLONG
712 wxDataOutputStream& wxDataOutputStream::operator<<(const wxULongLong &i)
713 {
714 WriteLL(i);
715 return *this;
716 }
717
718 wxDataOutputStream& wxDataOutputStream::operator<<(const wxLongLong &i)
719 {
720 WriteLL(i);
721 return *this;
722 }
723 #endif // wxLongLong_t
724
725 wxDataOutputStream& wxDataOutputStream::operator<<(double f)
726 {
727 WriteDouble(f);
728 return *this;
729 }
730
731 wxDataOutputStream& wxDataOutputStream::operator<<(float f)
732 {
733 WriteDouble((double)f);
734 return *this;
735 }
736
737 #endif
738 // wxUSE_STREAMS