Implement custom deserializer to add our own sanity checks
[quassel.git] / src / common / serializers / serializers.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 #include "serializers.h"
22
23 bool checkStreamValid(QDataStream &stream)
24 {
25     if (stream.status() != QDataStream::Ok) {
26         qWarning() << "Peer sent corrupt data";
27         return false;
28     }
29
30     return true;
31 }
32
33 bool Serializers::deserialize(QDataStream &stream, QVariantList &data)
34 {
35     uint32_t size;
36     if (!deserialize(stream, size))
37         return false;
38     if (size > 4 * 1024 * 1024) {
39         qWarning() << "Peer sent too large QVariantList: " << size;
40         return false;
41     }
42     for (uint32_t i = 0; i < size; i++) {
43         QVariant element;
44         if (!deserialize(stream, element))
45             return false;
46         data << element;
47     }
48     return checkStreamValid(stream);
49 }
50
51 bool Serializers::deserialize(QDataStream &stream, QVariantMap &data)
52 {
53     uint32_t size;
54     if (!deserialize(stream, size))
55         return false;
56     if (size > 4 * 1024 * 1024) {
57         qWarning() << "Peer sent too large QVariantMap: " << size;
58         return false;
59     }
60     for (uint32_t i = 0; i < size; i++) {
61         QString key;
62         QVariant value;
63         if (!deserialize(stream, key))
64             return false;
65         if (!deserialize(stream, value))
66             return false;
67         data[key] = value;
68     }
69     return checkStreamValid(stream);
70 }
71
72 bool Serializers::deserialize(QDataStream &stream, QVariant &data)
73 {
74     Types::VariantType type;
75     int8_t isNull;
76     if (!deserialize(stream, type))
77         return false;
78     if (!deserialize(stream, isNull))
79         return false;
80     if (type == Types::VariantType::UserType) {
81         QByteArray name;
82         if (!deserialize(stream, name))
83             return false;
84         while (name.length() > 0 && name.at(name.length() - 1) == 0)
85             name.chop(1);
86         if (!deserialize(stream, data, Types::fromName(name)))
87             return false;
88     } else {
89         if (!deserialize(stream, data, type))
90             return false;
91     }
92     return checkStreamValid(stream);
93 }
94
95 bool Serializers::deserialize(QDataStream &stream, QVariant &data, Types::VariantType type)
96 {
97     switch (type) {
98         case Types::VariantType::Void: {
99             return true;
100         }
101         case Types::VariantType::Bool: {
102             bool content;
103             if (!deserialize(stream, content))
104                 return false;
105             data = QVariant(content);
106             return true;
107         }
108         case Types::VariantType::Int: {
109             int32_t content;
110             if (!deserialize(stream, content))
111                 return false;
112             data = QVariant(content);
113             return true;
114         }
115         case Types::VariantType::UInt: {
116             uint32_t content;
117             if (!deserialize(stream, content))
118                 return false;
119             data = QVariant(content);
120             return true;
121         }
122         case Types::VariantType::QChar: {
123             QChar content;
124             if (!deserialize(stream, content))
125                 return false;
126             data = QVariant(content);
127             return true;
128         }
129         case Types::VariantType::QVariantMap: {
130             QVariantMap content;
131             if (!deserialize(stream, content))
132                 return false;
133             data = QVariant(content);
134             return true;
135         }
136         case Types::VariantType::QVariantList: {
137             QVariantList content;
138             if (!deserialize(stream, content))
139                 return false;
140             data = QVariant(content);
141             return true;
142         }
143         case Types::VariantType::QString: {
144             QString content;
145             if (!deserialize(stream, content))
146                 return false;
147             data = QVariant(content);
148             return true;
149         }
150         case Types::VariantType::QStringList: {
151             QStringList content;
152             if (!deserialize(stream, content))
153                 return false;
154             data = QVariant(content);
155             return true;
156         }
157         case Types::VariantType::QByteArray: {
158             QByteArray content;
159             if (!deserialize(stream, content))
160                 return false;
161             data = QVariant(content);
162             return true;
163         }
164         case Types::VariantType::QDate: {
165             QDate content;
166             if (!deserialize(stream, content))
167                 return false;
168             data = QVariant(content);
169             return true;
170         }
171         case Types::VariantType::QTime: {
172             QTime content;
173             if (!deserialize(stream, content))
174                 return false;
175             data = QVariant(content);
176             return true;
177         }
178         case Types::VariantType::QDateTime: {
179             QDateTime content;
180             if (!deserialize(stream, content))
181                 return false;
182             data = QVariant(content);
183             return true;
184         }
185         case Types::VariantType::Long: {
186             qlonglong content;
187             if (!deserialize(stream, content))
188                 return false;
189             data = QVariant(content);
190             return true;
191         }
192         case Types::VariantType::Short: {
193             int16_t content;
194             if (!deserialize(stream, content))
195                 return false;
196             data = QVariant(content);
197             return true;
198         }
199         case Types::VariantType::Char: {
200             int8_t content;
201             if (!deserialize(stream, content))
202                 return false;
203             data = QVariant(content);
204             return true;
205         }
206         case Types::VariantType::ULong: {
207             qulonglong content;
208             if (!deserialize(stream, content))
209                 return false;
210             data = QVariant(content);
211             return true;
212         }
213         case Types::VariantType::UShort: {
214             uint16_t content;
215             if (!deserialize(stream, content))
216                 return false;
217             data = QVariant(content);
218             return true;
219         }
220         case Types::VariantType::UChar: {
221             uint8_t content;
222             if (!deserialize(stream, content))
223                 return false;
224             data = QVariant(content);
225             return true;
226         }
227         case Types::VariantType::QVariant: {
228             QVariant content;
229             if (!deserialize(stream, content))
230                 return false;
231             data = QVariant(content);
232             return true;
233         }
234         default: {
235             qWarning() << "Usertype should have been caught earlier already";
236             return false;
237         }
238     }
239 }
240
241 bool Serializers::deserialize(QDataStream &stream, QVariant &data, Types::QuasselType type)
242 {
243     switch (type) {
244         case Types::QuasselType::BufferId: {
245             BufferId content;
246             if (!deserialize(stream, content))
247                 return false;
248             data = qVariantFromValue(content);
249             return true;
250         }
251         case Types::QuasselType::BufferInfo: {
252             BufferInfo content;
253             if (!deserialize(stream, content))
254                 return false;
255             data = qVariantFromValue(content);
256             return true;
257         }
258         case Types::QuasselType::Identity: {
259             Identity content;
260             if (!deserialize(stream, content))
261                 return false;
262             data = qVariantFromValue(content);
263             return true;
264         }
265         case Types::QuasselType::IdentityId: {
266             IdentityId content;
267             if (!deserialize(stream, content))
268                 return false;
269             data = qVariantFromValue(content);
270             return true;
271         }
272         case Types::QuasselType::Message: {
273             Message content;
274             if (!deserialize(stream, content))
275                 return false;
276             data = qVariantFromValue(content);
277             return true;
278         }
279         case Types::QuasselType::MsgId: {
280             MsgId content;
281             if (!deserialize(stream, content))
282                 return false;
283             data = qVariantFromValue(content);
284             return true;
285         }
286         case Types::QuasselType::NetworkId: {
287             NetworkId content;
288             if (!deserialize(stream, content))
289                 return false;
290             data = qVariantFromValue(content);
291             return true;
292         }
293         case Types::QuasselType::NetworkInfo: {
294             NetworkInfo content;
295             if (!deserialize(stream, content))
296                 return false;
297             data = qVariantFromValue(content);
298             return true;
299         }
300         case Types::QuasselType::Network_Server: {
301             Network::Server content;
302             if (!deserialize(stream, content))
303                 return false;
304             data = qVariantFromValue(content);
305             return true;
306         }
307         case Types::QuasselType::PeerPtr: {
308             PeerPtr content;
309             if (!deserialize(stream, content))
310                 return false;
311             data = qVariantFromValue(content);
312             return true;
313         }
314         default: {
315             qWarning() << "Invalid QType";
316             return false;
317         }
318     }
319 }
320
321 bool Serializers::deserialize(QDataStream &stream, Types::VariantType &data)
322 {
323     uint32_t raw;
324     if (!deserialize(stream, raw))
325         return false;
326     data = static_cast<Types::VariantType>(raw);
327     return checkStreamValid(stream);
328 }
329
330 bool Serializers::deserialize(QDataStream &stream, QStringList &data)
331 {
332     uint32_t size;
333     if (!deserialize(stream, size))
334         return false;
335     for (uint32_t i = 0; i < size; i++) {
336         QString element;
337         if (!deserialize(stream, element))
338             return false;
339         data << element;
340     }
341     return checkStreamValid(stream);
342 }
343
344 bool Serializers::deserialize(QDataStream &stream, Network::Server &server)
345 {
346     QVariantMap serverMap;
347     if (!deserialize(stream, serverMap))
348         return false;
349     server.host = serverMap["Host"].toString();
350     server.port = serverMap["Port"].toUInt();
351     server.password = serverMap["Password"].toString();
352     server.useSsl = serverMap["UseSSL"].toBool();
353     server.sslVersion = serverMap["sslVersion"].toInt();
354     server.useProxy = serverMap["UseProxy"].toBool();
355     server.proxyType = serverMap["ProxyType"].toInt();
356     server.proxyHost = serverMap["ProxyHost"].toString();
357     server.proxyPort = serverMap["ProxyPort"].toUInt();
358     server.proxyUser = serverMap["ProxyUser"].toString();
359     server.proxyPass = serverMap["ProxyPass"].toString();
360     return checkStreamValid(stream);
361 }
362
363 bool Serializers::deserialize(QDataStream &stream, Identity &data)
364 {
365     QVariantMap raw;
366     if (!deserialize(stream, raw))
367         return false;
368     data.fromVariantMap(raw);
369     return checkStreamValid(stream);
370 }
371
372 bool Serializers::deserialize(QDataStream &stream, NetworkInfo &info)
373 {
374     QVariantMap i;
375     if (!deserialize(stream, i))
376         return false;
377     info.networkId = i["NetworkId"].value<NetworkId>();
378     info.networkName = i["NetworkName"].toString();
379     info.identity = i["Identity"].value<IdentityId>();
380     info.codecForServer = i["CodecForServer"].toByteArray();
381     info.codecForEncoding = i["CodecForEncoding"].toByteArray();
382     info.codecForDecoding = i["CodecForDecoding"].toByteArray();
383     info.serverList = fromVariantList<Network::Server>(i["ServerList"].toList());
384     info.useRandomServer = i["UseRandomServer"].toBool();
385     info.perform = i["Perform"].toStringList();
386     info.useAutoIdentify = i["UseAutoIdentify"].toBool();
387     info.autoIdentifyService = i["AutoIdentifyService"].toString();
388     info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString();
389     info.useSasl = i["UseSasl"].toBool();
390     info.saslAccount = i["SaslAccount"].toString();
391     info.saslPassword = i["SaslPassword"].toString();
392     info.useAutoReconnect = i["UseAutoReconnect"].toBool();
393     info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt();
394     info.autoReconnectRetries = i["AutoReconnectRetries"].toInt();
395     info.unlimitedReconnectRetries = i["UnlimitedReconnectRetries"].toBool();
396     info.rejoinChannels = i["RejoinChannels"].toBool();
397     return checkStreamValid(stream);
398 }
399
400 bool Serializers::deserialize(QDataStream &stream, PeerPtr &data)
401 {
402     stream >> data;
403     return checkStreamValid(stream);
404 }
405
406 bool Serializers::deserialize(QDataStream &stream, QByteArray &data)
407 {
408     data.clear();
409     uint32_t length;
410     if (!deserialize(stream, length))
411         return false;
412     // -1 - or 0xffffffff - is used for an empty byte array
413     if (length == 0xffffffff) {
414         return true;
415     }
416
417     // 64 MB should be enough
418     if (length > 64 * 1024 * 1024) {
419         qWarning() << "Peer sent too large QByteArray: " << length;
420         return false;
421     }
422
423     const uint32_t Step = 1024 * 1024;
424     uint32_t allocated = 0;
425     do {
426         int blockSize = std::min(Step, length - allocated);
427         data.resize(allocated + blockSize);
428         if (stream.readRawData(data.data() + allocated, blockSize) != blockSize) {
429             data.clear();
430             qWarning() << "BufferUnderFlow while reading QByteArray";
431             return false;
432         }
433         allocated += blockSize;
434     } while (allocated < length);
435     return checkStreamValid(stream);
436 }
437
438 bool Serializers::deserialize(QDataStream &stream, QString &data)
439 {
440     uint32_t bytes = 0;
441     // read size of string
442     if (!deserialize(stream, bytes))
443         return false;
444
445     // empty string
446     if (bytes == 0) {
447         return true;
448     }
449
450     // null string
451     if (bytes == 0xffffffff) {
452         data.clear();
453         return true;
454     }
455
456     // 64 MB should be enough
457     if (bytes > 64 * 1024 * 1024) {
458         qWarning() << "Peer sent too large QString: " << bytes;
459         return false;
460     }
461
462     if (bytes & 0x1) {
463         data.clear();
464         qWarning() << "Read corrupted data: UTF-6 String with odd length: " << bytes;
465         return false;
466     }
467     const uint32_t step = 1024 * 1024;
468     uint32_t length = bytes / 2;
469     uint32_t allocated = 0;
470     while (allocated < length) {
471         int blockSize = std::min(step, length - allocated);
472         data.resize(allocated + blockSize);
473         if (stream.readRawData(reinterpret_cast<char *>(data.data()) + allocated * 2, blockSize * 2) != blockSize * 2) {
474             data.clear();
475             qWarning() << "BufferUnderFlow while reading QString";
476             return false;
477         }
478         allocated += blockSize;
479     }
480     if ((stream.byteOrder() == QDataStream::BigEndian) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
481         uint16_t *rawData = reinterpret_cast<uint16_t *>(data.data());
482         while (length--) {
483             *rawData = qbswap(*rawData);
484             ++rawData;
485         }
486     }
487     return checkStreamValid(stream);
488 }
489
490 bool Serializers::deserialize(QDataStream &stream, QChar &data)
491 {
492     stream >> data;
493     return checkStreamValid(stream);
494 }
495
496 bool Serializers::deserialize(QDataStream &stream, QDate &data)
497 {
498     stream >> data;
499     return checkStreamValid(stream);
500 }
501
502 bool Serializers::deserialize(QDataStream &stream, QTime &data)
503 {
504     stream >> data;
505     return checkStreamValid(stream);
506 }
507
508 bool Serializers::deserialize(QDataStream &stream, QDateTime &data)
509 {
510     stream >> data;
511     return checkStreamValid(stream);
512 }
513
514 bool Serializers::deserialize(QDataStream &stream, int32_t &data)
515 {
516     stream >> data;
517     return checkStreamValid(stream);
518 }
519
520 bool Serializers::deserialize(QDataStream &stream, uint32_t &data)
521 {
522     stream >> data;
523     return checkStreamValid(stream);
524 }
525
526 bool Serializers::deserialize(QDataStream &stream, int16_t &data)
527 {
528     stream >> data;
529     return checkStreamValid(stream);
530 }
531
532 bool Serializers::deserialize(QDataStream &stream, uint16_t &data)
533 {
534     stream >> data;
535     return checkStreamValid(stream);
536 }
537
538 bool Serializers::deserialize(QDataStream &stream, int8_t &data)
539 {
540     stream >> data;
541     return checkStreamValid(stream);
542 }
543
544 bool Serializers::deserialize(QDataStream &stream, uint8_t &data)
545 {
546     stream >> data;
547     return checkStreamValid(stream);
548 }
549
550 bool Serializers::deserialize(QDataStream &stream, qlonglong &data)
551 {
552     stream >> data;
553     return checkStreamValid(stream);
554 }
555
556 bool Serializers::deserialize(QDataStream &stream, qulonglong &data)
557 {
558     stream >> data;
559     return checkStreamValid(stream);
560 }
561
562 bool Serializers::deserialize(QDataStream &stream, bool &data)
563 {
564     stream >> data;
565     return checkStreamValid(stream);
566 }
567
568 bool Serializers::deserialize(QDataStream &stream, BufferInfo &data)
569 {
570     stream >> data;
571     return checkStreamValid(stream);
572 }
573
574 bool Serializers::deserialize(QDataStream &stream, Message &data)
575 {
576     stream >> data;
577     return checkStreamValid(stream);
578 }
579
580 bool Serializers::deserialize(QDataStream &stream, NetworkId &data)
581 {
582     stream >> data;
583     return checkStreamValid(stream);
584 }
585
586 bool Serializers::deserialize(QDataStream &stream, IdentityId &data)
587 {
588     stream >> data;
589     return checkStreamValid(stream);
590 }
591
592 bool Serializers::deserialize(QDataStream &stream, BufferId &data)
593 {
594     stream >> data;
595     return checkStreamValid(stream);
596 }
597
598 bool Serializers::deserialize(QDataStream &stream, MsgId &data)
599 {
600     stream >> data;
601     return checkStreamValid(stream);
602 }
603
604 Serializers::Types::VariantType Serializers::Types::variantType(Serializers::Types::QuasselType type)
605 {
606     switch (type) {
607         case QuasselType::BufferId:
608             return VariantType::UserType;
609         case QuasselType::BufferInfo:
610             return VariantType::UserType;
611         case QuasselType::Identity:
612             return VariantType::UserType;
613         case QuasselType::IdentityId:
614             return VariantType::UserType;
615         case QuasselType::Message:
616             return VariantType::UserType;
617         case QuasselType::MsgId:
618             return VariantType::UserType;
619         case QuasselType::NetworkId:
620             return VariantType::UserType;
621         case QuasselType::NetworkInfo:
622             return VariantType::UserType;
623         case QuasselType::Network_Server:
624             return VariantType::UserType;
625         case QuasselType::PeerPtr:
626             return VariantType::Long;
627         default:
628             return VariantType::UserType;
629     }
630 }
631
632 QString Serializers::Types::toName(Serializers::Types::QuasselType type)
633 {
634     switch (type) {
635         case QuasselType::BufferId:
636             return QString("BufferId");
637         case QuasselType::BufferInfo:
638             return QString("BufferInfo");
639         case QuasselType::Identity:
640             return QString("Identity");
641         case QuasselType::IdentityId:
642             return QString("IdentityId");
643         case QuasselType::Message:
644             return QString("Message");
645         case QuasselType::MsgId:
646             return QString("MsgId");
647         case QuasselType::NetworkId:
648             return QString("NetworkId");
649         case QuasselType::NetworkInfo:
650             return QString("NetworkInfo");
651         case QuasselType::Network_Server:
652             return QString("Network::Server");
653         case QuasselType::PeerPtr:
654             return QString("PeerPtr");
655         default:
656             return QString("Invalid Type");
657     }
658 }
659
660 Serializers::Types::QuasselType Serializers::Types::fromName(::QByteArray &name)
661 {
662     if (qstrcmp(name, "BufferId") == 0) return QuasselType::BufferId;
663     else if (qstrcmp(name, "BufferInfo") == 0) return QuasselType::BufferInfo;
664     else if (qstrcmp(name, "Identity") == 0) return QuasselType::Identity;
665     else if (qstrcmp(name, "IdentityId") == 0) return QuasselType::IdentityId;
666     else if (qstrcmp(name, "Message") == 0) return QuasselType::Message;
667     else if (qstrcmp(name, "MsgId") == 0) return QuasselType::MsgId;
668     else if (qstrcmp(name, "NetworkId") == 0) return QuasselType::NetworkId;
669     else if (qstrcmp(name, "NetworkInfo") == 0) return QuasselType::NetworkInfo;
670     else if (qstrcmp(name, "Network::Server") == 0) return QuasselType::Network_Server;
671     else if (qstrcmp(name, "PeerPtr") == 0) return QuasselType::PeerPtr;
672     else {
673         qWarning() << "Type name is not valid: " << name;
674         return QuasselType::Invalid;
675     }
676 }