Bug Summary

File:/boot/home/haiku/haiku/src/kits/mail/MailAttachment.cpp
Location:line 174, column 2
Description:Size argument is greater than the length of the destination buffer

Annotated Source Code

1/*
2 * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
3 */
4
5
6/*! Classes which handle mail attachments */
7
8
9#include <MailAttachment.h>
10
11#include <stdlib.h>
12#include <stdio.h>
13
14#include <ByteOrder.h>
15#include <DataIO.h>
16#include <Entry.h>
17#include <File.h>
18#include <Mime.h>
19#include <NodeInfo.h>
20#include <String.h>
21
22#include <AutoDeleter.h>
23
24#include <mail_encoding.h>
25#include <NodeMessage.h>
26
27
28/*! No attributes or awareness of the file system at large
29*/
30BSimpleMailAttachment::BSimpleMailAttachment()
31 :
32 fStatus(B_NO_INIT((-2147483647 - 1) + 13)),
33 _data(NULL__null),
34 _raw_data(NULL__null),
35 _we_own_data(false)
36{
37 Initialize(base64);
38}
39
40
41BSimpleMailAttachment::BSimpleMailAttachment(BPositionIO *data,
42 mail_encoding encoding)
43 :
44 _data(data),
45 _raw_data(NULL__null),
46 _we_own_data(false)
47{
48 fStatus = data == NULL__null ? B_BAD_VALUE((-2147483647 - 1) + 5) : B_OK((int)0);
49
50 Initialize(encoding);
51}
52
53
54BSimpleMailAttachment::BSimpleMailAttachment(const void *data, size_t length,
55 mail_encoding encoding)
56 :
57 _data(new BMemoryIO(data,length)),
58 _raw_data(NULL__null),
59 _we_own_data(true)
60{
61 fStatus = data == NULL__null ? B_BAD_VALUE((-2147483647 - 1) + 5) : B_OK((int)0);
62
63 Initialize(encoding);
64}
65
66
67BSimpleMailAttachment::BSimpleMailAttachment(BFile *file, bool deleteWhenDone)
68 :
69 _data(NULL__null),
70 _raw_data(NULL__null),
71 _we_own_data(false)
72{
73 Initialize(base64);
74 SetTo(file, deleteWhenDone);
75}
76
77
78BSimpleMailAttachment::BSimpleMailAttachment(entry_ref *ref)
79 :
80 _data(NULL__null),
81 _raw_data(NULL__null),
82 _we_own_data(false)
83{
84 Initialize(base64);
85 SetTo(ref);
86}
87
88
89BSimpleMailAttachment::~BSimpleMailAttachment()
90{
91 if (_we_own_data)
92 delete _data;
93}
94
95
96void
97BSimpleMailAttachment::Initialize(mail_encoding encoding)
98{
99 SetEncoding(encoding);
100 SetHeaderField("Content-Disposition","BMailAttachment");
101}
102
103
104status_t
105BSimpleMailAttachment::SetTo(BFile *file, bool deleteFileWhenDone)
106{
107 char type[B_MIME_TYPE_LENGTH(((256)-1) - 15)] = "application/octet-stream";
108
109 BNodeInfo nodeInfo(file);
110 if (nodeInfo.InitCheck() == B_OK((int)0))
111 nodeInfo.GetType(type);
112
113 SetHeaderField("Content-Type", type);
114 // TODO: No way to get file name (see SetTo(entry_ref *))
115 //SetFileName(ref->name);
116
117 if (deleteFileWhenDone)
118 SetDecodedDataAndDeleteWhenDone(file);
119 else
120 SetDecodedData(file);
121
122 return fStatus = B_OK((int)0);
123}
124
125
126status_t
127BSimpleMailAttachment::SetTo(entry_ref *ref)
128{
129 BFile *file = new BFile(ref, B_READ_ONLY0x0000);
130 if ((fStatus = file->InitCheck()) < B_OK((int)0)) {
131 delete file;
132 return fStatus;
133 }
134
135 if (SetTo(file, true) != B_OK((int)0))
136 return fStatus;
137
138 SetFileName(ref->name);
139 return fStatus = B_OK((int)0);
140}
141
142
143status_t
144BSimpleMailAttachment::InitCheck()
145{
146 return fStatus;
147}
148
149
150status_t
151BSimpleMailAttachment::FileName(char *text)
152{
153 BMessage contentType;
154 HeaderField("Content-Type", &contentType);
155
156 const char *fileName = contentType.FindString("name");
157 if (!fileName)
2
Assuming 'fileName' is non-null
3
Taking false branch
158 fileName = contentType.FindString("filename");
159 if (!fileName) {
4
Taking false branch
160 contentType.MakeEmpty();
161 HeaderField("Content-Disposition", &contentType);
162 fileName = contentType.FindString("name");
163 }
164 if (!fileName)
5
Taking false branch
165 fileName = contentType.FindString("filename");
166 if (!fileName) {
6
Taking false branch
167 contentType.MakeEmpty();
168 HeaderField("Content-Location", &contentType);
169 fileName = contentType.FindString("unlabeled");
170 }
171 if (!fileName)
7
Taking false branch
172 return B_NAME_NOT_FOUND((-2147483647 - 1) + 7);
173
174 strncpy(text, fileName, B_FILE_NAME_LENGTH(256));
8
Size argument is greater than the length of the destination buffer
175 return B_OK((int)0);
176}
177
178
179void
180BSimpleMailAttachment::SetFileName(const char *name)
181{
182 BMessage contentType;
183 HeaderField("Content-Type", &contentType);
184
185 if (contentType.ReplaceString("name", name) != B_OK((int)0))
186 contentType.AddString("name", name);
187
188 // Request that the file name header be encoded in UTF-8 if it has weird
189 // characters. If it is just a plain name, the header will appear normal.
190 if (contentType.ReplaceInt32(kHeaderCharsetString, B_MAIL_UTF8_CONVERSION((uint32) -2))
191 != B_OK((int)0))
192 contentType.AddInt32(kHeaderCharsetString, B_MAIL_UTF8_CONVERSION((uint32) -2));
193
194 SetHeaderField ("Content-Type", &contentType);
195}
196
197
198status_t
199BSimpleMailAttachment::GetDecodedData(BPositionIO *data)
200{
201 ParseNow();
202
203 if (!_data)
204 return B_IO_ERROR((-2147483647 - 1) + 1);
205 if (data == NULL__null)
206 return B_BAD_VALUE((-2147483647 - 1) + 5);
207
208 char buffer[256];
209 ssize_t length;
210 _data->Seek(0,SEEK_SET0);
211
212 while ((length = _data->Read(buffer, sizeof(buffer))) > 0)
213 data->Write(buffer, length);
214
215 return B_OK((int)0);
216}
217
218
219BPositionIO *
220BSimpleMailAttachment::GetDecodedData()
221{
222 ParseNow();
223 return _data;
224}
225
226
227status_t
228BSimpleMailAttachment::SetDecodedDataAndDeleteWhenDone(BPositionIO *data)
229{
230 _raw_data = NULL__null;
231
232 if (_we_own_data)
233 delete _data;
234
235 _data = data;
236 _we_own_data = true;
237
238 return B_OK((int)0);
239}
240
241
242status_t
243BSimpleMailAttachment::SetDecodedData(BPositionIO *data)
244{
245 _raw_data = NULL__null;
246
247 if (_we_own_data)
248 delete _data;
249
250 _data = data;
251 _we_own_data = false;
252
253 return B_OK((int)0);
254}
255
256
257status_t
258BSimpleMailAttachment::SetDecodedData(const void *data, size_t length)
259{
260 _raw_data = NULL__null;
261
262 if (_we_own_data)
263 delete _data;
264
265 _data = new BMemoryIO(data,length);
266 _we_own_data = true;
267
268 return B_OK((int)0);
269}
270
271
272void
273BSimpleMailAttachment::SetEncoding(mail_encoding encoding)
274{
275 _encoding = encoding;
276
277 const char *cte = NULL__null; //--Content Transfer Encoding
278 switch (_encoding) {
279 case base64:
280 cte = "base64";
281 break;
282 case seven_bit:
283 case no_encoding:
284 cte = "7bit";
285 break;
286 case eight_bit:
287 cte = "8bit";
288 break;
289 case uuencode:
290 cte = "uuencode";
291 break;
292 case quoted_printable:
293 cte = "quoted-printable";
294 break;
295 default:
296 cte = "bug-not-implemented";
297 break;
298 }
299
300 SetHeaderField("Content-Transfer-Encoding", cte);
301}
302
303
304mail_encoding
305BSimpleMailAttachment::Encoding()
306{
307 return _encoding;
308}
309
310
311status_t
312BSimpleMailAttachment::SetToRFC822(BPositionIO *data, size_t length,
313 bool parseNow)
314{
315 //---------Massive memory squandering!---ALERT!----------
316 if (_we_own_data)
317 delete _data;
318
319 off_t position = data->Position();
320 BMailComponent::SetToRFC822(data, length, parseNow);
321
322 // this actually happens...
323 if (data->Position() - position > (off_t)length)
324 return B_ERROR(-1);
325
326 length -= (data->Position() - position);
327
328 _raw_data = data;
329 _raw_length = length;
330 _raw_offset = data->Position();
331
332 BString encoding = HeaderField("Content-Transfer-Encoding");
333 if (encoding.IFindFirst("base64") >= 0)
334 _encoding = base64;
335 else if (encoding.IFindFirst("quoted-printable") >= 0)
336 _encoding = quoted_printable;
337 else if (encoding.IFindFirst("uuencode") >= 0)
338 _encoding = uuencode;
339 else if (encoding.IFindFirst("7bit") >= 0)
340 _encoding = seven_bit;
341 else if (encoding.IFindFirst("8bit") >= 0)
342 _encoding = eight_bit;
343 else
344 _encoding = no_encoding;
345
346 if (parseNow)
347 ParseNow();
348
349 return B_OK((int)0);
350}
351
352
353void
354BSimpleMailAttachment::ParseNow()
355{
356 if (_raw_data == NULL__null || _raw_length == 0)
357 return;
358
359 _raw_data->Seek(_raw_offset, SEEK_SET0);
360
361 char *src = (char *)malloc(_raw_length);
362 if (src == NULL__null)
363 return;
364
365 size_t size = _raw_length;
366
367 size = _raw_data->Read(src, _raw_length);
368
369 BMallocIO *buffer = new BMallocIO;
370 buffer->SetSize(size);
371 // 8bit is *always* more efficient than an encoding, so the buffer
372 // will *never* be larger than before
373
374 size = decode(_encoding,(char *)(buffer->Buffer()),src,size,0);
375 free(src);
376
377 buffer->SetSize(size);
378
379 _data = buffer;
380 _we_own_data = true;
381
382 _raw_data = NULL__null;
383
384 return;
385}
386
387
388status_t
389BSimpleMailAttachment::RenderToRFC822(BPositionIO *renderTo)
390{
391 ParseNow();
392 BMailComponent::RenderToRFC822(renderTo);
393 //---------Massive memory squandering!---ALERT!----------
394
395 _data->Seek(0, SEEK_END2);
396 off_t size = _data->Position();
397 char *src = (char *)malloc(size);
398 if (src == NULL__null)
399 return B_NO_MEMORY((-2147483647 - 1) + 0);
400
401 MemoryDeleter sourceDeleter(src);
402
403 _data->Seek(0, SEEK_SET0);
404
405 ssize_t read = _data->Read(src, size);
406 if (read < B_OK((int)0))
407 return read;
408
409 // The encoded text will never be more than twice as large with any
410 // conceivable encoding. But just in case, there's a function call which
411 // will tell us how much space is needed.
412 ssize_t destSize = max_encoded_length(_encoding, read);
413 if (destSize < B_OK((int)0)) // Invalid encodings like uuencode rejected here.
414 return destSize;
415 char *dest = (char *)malloc(destSize);
416 if (dest == NULL__null)
417 return B_NO_MEMORY((-2147483647 - 1) + 0);
418
419 MemoryDeleter destinationDeleter(dest);
420
421 destSize = encode (_encoding, dest, src, read, false /* headerMode */);
422 if (destSize < B_OK((int)0))
423 return destSize;
424
425 if (destSize > 0)
426 read = renderTo->Write(dest, destSize);
427
428 return read > 0 ? B_OK((int)0) : read;
429}
430
431
432// #pragma mark -
433
434
435/*! Supports and sends attributes.
436*/
437BAttributedMailAttachment::BAttributedMailAttachment()
438 :
439 fContainer(NULL__null),
440 fStatus(B_NO_INIT((-2147483647 - 1) + 13)),
441 _data(NULL__null),
442 _attributes_attach(NULL__null)
443{
444}
445
446
447BAttributedMailAttachment::BAttributedMailAttachment(BFile *file,
448 bool deleteWhenDone)
449 :
450 fContainer(NULL__null),
451 _data(NULL__null),
452 _attributes_attach(NULL__null)
453{
454 SetTo(file, deleteWhenDone);
455}
456
457
458BAttributedMailAttachment::BAttributedMailAttachment(entry_ref *ref)
459 :
460 fContainer(NULL__null),
461 _data(NULL__null),
462 _attributes_attach(NULL__null)
463{
464 SetTo(ref);
465}
466
467
468BAttributedMailAttachment::~BAttributedMailAttachment()
469{
470 // Our SimpleAttachments are deleted by fContainer
471 delete fContainer;
472}
473
474
475status_t
476BAttributedMailAttachment::Initialize()
477{
478 // _data & _attributes_attach will be deleted by the container
479 delete fContainer;
480
481 fContainer = new BMIMEMultipartMailContainer("++++++BFile++++++");
482
483 _data = new BSimpleMailAttachment();
484 fContainer->AddComponent(_data);
485
486 _attributes_attach = new BSimpleMailAttachment();
487 _attributes.MakeEmpty();
488 _attributes_attach->SetHeaderField("Content-Type",
489 "application/x-be_attribute; name=\"BeOS Attributes\"");
490 fContainer->AddComponent(_attributes_attach);
491
492 fContainer->SetHeaderField("Content-Type", "multipart/x-bfile");
493 fContainer->SetHeaderField("Content-Disposition", "BMailAttachment");
494
495 // also set the header fields of this component, in case someone asks
496 SetHeaderField("Content-Type", "multipart/x-bfile");
497 SetHeaderField("Content-Disposition", "BMailAttachment");
498
499 return B_OK((int)0);
500}
501
502
503status_t
504BAttributedMailAttachment::SetTo(BFile *file, bool deleteFileWhenDone)
505{
506 if (file == NULL__null)
507 return fStatus = B_BAD_VALUE((-2147483647 - 1) + 5);
508
509 if ((fStatus = Initialize()) < B_OK((int)0))
510 return fStatus;
511
512 _attributes << *file;
513
514 if ((fStatus = _data->SetTo(file, deleteFileWhenDone)) < B_OK((int)0))
515 return fStatus;
516
517 // Set boundary
518
519 // Also, we have the make up the boundary out of whole cloth
520 // This is likely to give a completely random string
521 BString boundary;
522 boundary << "BFile--" << ((long)file ^ time(NULL__null)) << "-"
523 << ~((long)file ^ (long)&fStatus ^ (long)&_attributes) << "--";
524 fContainer->SetBoundary(boundary.String());
525
526 return fStatus = B_OK((int)0);
527}
528
529
530status_t
531BAttributedMailAttachment::SetTo(entry_ref *ref)
532{
533 if (ref == NULL__null)
534 return fStatus = B_BAD_VALUE((-2147483647 - 1) + 5);
535
536 if ((fStatus = Initialize()) < B_OK((int)0))
537 return fStatus;
538
539 BNode node(ref);
540 if ((fStatus = node.InitCheck()) < B_OK((int)0))
541 return fStatus;
542
543 _attributes << node;
544
545 if ((fStatus = _data->SetTo(ref)) < B_OK((int)0))
546 return fStatus;
547
548 // Set boundary
549
550 // This is likely to give a completely random string
551 BString boundary;
552 char buffer[512];
553 strcpy(buffer, ref->name);
554 for (int32 i = strlen(buffer); i-- > 0;) {
555 if (buffer[i] & 0x80)
556 buffer[i] = 'x';
557 else if (buffer[i] == ' ' || buffer[i] == ':')
558 buffer[i] = '_';
559 }
560 buffer[32] = '\0';
561 boundary << "BFile-" << buffer << "--" << ((long)_data ^ time(NULL__null))
562 << "-" << ~((long)_data ^ (long)&buffer ^ (long)&_attributes)
563 << "--";
564 fContainer->SetBoundary(boundary.String());
565
566 return fStatus = B_OK((int)0);
567}
568
569
570status_t
571BAttributedMailAttachment::InitCheck()
572{
573 return fStatus;
574}
575
576
577void
578BAttributedMailAttachment::SaveToDisk(BEntry *entry)
579{
580 BString path = "/tmp/";
581 char name[255] = "";
582 _data->FileName(name);
1
Calling 'BSimpleMailAttachment::FileName'
583 path << name;
584
585 BFile file(path.String(), B_READ_WRITE0x0002 | B_CREATE_FILE0x0200);
586 (BNode&)file << _attributes;
587 _data->GetDecodedData(&file);
588 file.Sync();
589
590 entry->SetTo(path.String());
591}
592
593
594void
595BAttributedMailAttachment::SetEncoding(mail_encoding encoding)
596{
597 _data->SetEncoding(encoding);
598 if (_attributes_attach != NULL__null)
599 _attributes_attach->SetEncoding(encoding);
600}
601
602
603mail_encoding
604BAttributedMailAttachment::Encoding()
605{
606 return _data->Encoding();
607}
608
609
610status_t
611BAttributedMailAttachment::FileName(char *name)
612{
613 return _data->FileName(name);
614}
615
616
617void
618BAttributedMailAttachment::SetFileName(const char *name)
619{
620 _data->SetFileName(name);
621}
622
623
624status_t
625BAttributedMailAttachment::GetDecodedData(BPositionIO *data)
626{
627 BNode *node = dynamic_cast<BNode *>(data);
628 if (node != NULL__null)
629 *node << _attributes;
630
631 _data->GetDecodedData(data);
632 return B_OK((int)0);
633}
634
635
636status_t
637BAttributedMailAttachment::SetDecodedData(BPositionIO *data)
638{
639 BNode *node = dynamic_cast<BNode *>(data);
640 if (node != NULL__null)
641 _attributes << *node;
642
643 _data->SetDecodedData(data);
644 return B_OK((int)0);
645}
646
647
648status_t
649BAttributedMailAttachment::SetToRFC822(BPositionIO *data, size_t length,
650 bool parseNow)
651{
652 status_t err = Initialize();
653 if (err < B_OK((int)0))
654 return err;
655
656 err = fContainer->SetToRFC822(data, length, parseNow);
657 if (err < B_OK((int)0))
658 return err;
659
660 BMimeType type;
661 fContainer->MIMEType(&type);
662 if (strcmp(type.Type(), "multipart/x-bfile") != 0)
663 return B_BAD_TYPE((-2147483647 - 1) + 4);
664
665 // get data and attributes
666 if ((_data = dynamic_cast<BSimpleMailAttachment *>(
667 fContainer->GetComponent(0))) == NULL__null)
668 return B_BAD_VALUE((-2147483647 - 1) + 5);
669
670 if (parseNow) {
671 // Force it to make a copy of the data. Needed for forwarding
672 // messages hack.
673 _data->GetDecodedData();
674 }
675
676 if ((_attributes_attach = dynamic_cast<BSimpleMailAttachment *>(
677 fContainer->GetComponent(1))) == NULL__null
678 || _attributes_attach->GetDecodedData() == NULL__null)
679 return B_OK((int)0);
680
681 // Convert the attribute binary attachment into a convenient easy to use
682 // BMessage.
683
684 int32 len
685 = ((BMallocIO *)(_attributes_attach->GetDecodedData()))->BufferLength();
686 char *start = (char *)malloc(len);
687 if (start == NULL__null)
688 return B_NO_MEMORY((-2147483647 - 1) + 0);
689
690 MemoryDeleter deleter(start);
691
692 if (_attributes_attach->GetDecodedData()->ReadAt(0, start, len) < len)
693 return B_IO_ERROR((-2147483647 - 1) + 1);
694
695 int32 index = 0;
696 while (index < len) {
697 char *name = &start[index];
698 index += strlen(name) + 1;
699
700 type_code code;
701 memcpy(&code, &start[index], sizeof(type_code));
702 code = B_BENDIAN_TO_HOST_INT32(code)__swap_int32(code);
703 index += sizeof(type_code);
704
705 int64 buf_length;
706 memcpy(&buf_length, &start[index], sizeof(buf_length));
707 buf_length = B_BENDIAN_TO_HOST_INT64(buf_length)__swap_int64(buf_length);
708 index += sizeof(buf_length);
709
710 swap_data(code, &start[index], buf_length, B_SWAP_BENDIAN_TO_HOST);
711 _attributes.AddData(name, code, &start[index], buf_length);
712 index += buf_length;
713 }
714
715 return B_OK((int)0);
716}
717
718
719status_t
720BAttributedMailAttachment::RenderToRFC822(BPositionIO *renderTo)
721{
722 BMallocIO *io = new BMallocIO;
723
724#if defined(HAIKU_TARGET_PLATFORM_DANO)
725 const
726#endif
727 char *name;
728 type_code type;
729 for (int32 i = 0; _attributes.GetInfo(B_ANY_TYPE, i, &name, &type) == B_OK((int)0);
730 i++) {
731 const void *data;
732 ssize_t dataLen;
733 _attributes.FindData(name, type, &data, &dataLen);
734 io->Write(name, strlen(name) + 1);
735
736 type_code swappedType = B_HOST_TO_BENDIAN_INT32(type)__swap_int32(type);
737 io->Write(&swappedType, sizeof(type_code));
738
739 int64 length, swapped;
740 length = dataLen;
741 swapped = B_HOST_TO_BENDIAN_INT64(length)__swap_int64(length);
742 io->Write(&swapped,sizeof(int64));
743
744 void *buffer = malloc(dataLen);
745 if (buffer == NULL__null) {
746 delete io;
747 return B_NO_MEMORY((-2147483647 - 1) + 0);
748 }
749 memcpy(buffer, data, dataLen);
750 swap_data(type, buffer, dataLen, B_SWAP_HOST_TO_BENDIAN);
751 io->Write(buffer, dataLen);
752 free(buffer);
753 }
754 if (_attributes_attach == NULL__null)
755 _attributes_attach = new BSimpleMailAttachment;
756
757 _attributes_attach->SetDecodedDataAndDeleteWhenDone(io);
758
759 return fContainer->RenderToRFC822(renderTo);
760}
761
762
763status_t
764BAttributedMailAttachment::MIMEType(BMimeType *mime)
765{
766 return _data->MIMEType(mime);
767}
768
769
770// #pragma mark - The reserved function stubs
771
772
773void BMailAttachment::_ReservedAttachment1() {}
774void BMailAttachment::_ReservedAttachment2() {}
775void BMailAttachment::_ReservedAttachment3() {}
776void BMailAttachment::_ReservedAttachment4() {}
777
778void BSimpleMailAttachment::_ReservedSimple1() {}
779void BSimpleMailAttachment::_ReservedSimple2() {}
780void BSimpleMailAttachment::_ReservedSimple3() {}
781
782void BAttributedMailAttachment::_ReservedAttributed1() {}
783void BAttributedMailAttachment::_ReservedAttributed2() {}
784void BAttributedMailAttachment::_ReservedAttributed3() {}