aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llsdserialize.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:34 -0500
committerJacek Antonelli2008-08-15 23:45:34 -0500
commitcd17687f01420952712a500107e0f93e7ab8d5f8 (patch)
treece48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/llcommon/llsdserialize.cpp
parentSecond Life viewer sources 1.19.0.5 (diff)
downloadmeta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.zip
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.gz
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.bz2
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.xz
Second Life viewer sources 1.19.1.0
Diffstat (limited to 'linden/indra/llcommon/llsdserialize.cpp')
-rw-r--r--linden/indra/llcommon/llsdserialize.cpp763
1 files changed, 545 insertions, 218 deletions
diff --git a/linden/indra/llcommon/llsdserialize.cpp b/linden/indra/llcommon/llsdserialize.cpp
index 7813cf0..a556d5d 100644
--- a/linden/indra/llcommon/llsdserialize.cpp
+++ b/linden/indra/llcommon/llsdserialize.cpp
@@ -45,26 +45,18 @@
45 45
46#include "lldate.h" 46#include "lldate.h"
47#include "llsd.h" 47#include "llsd.h"
48#include "llstring.h"
48#include "lluri.h" 49#include "lluri.h"
49 50
50// File constants 51// File constants
51static const int MAX_HDR_LEN = 20; 52static const int MAX_HDR_LEN = 20;
52static const char LEGACY_NON_HEADER[] = "<llsd>"; 53static const char LEGACY_NON_HEADER[] = "<llsd>";
54const std::string LLSD_BINARY_HEADER("LLSD/Binary");
55const std::string LLSD_XML_HEADER("LLSD/XML");
53 56
54//static 57/**
55const char* LLSDSerialize::LLSDBinaryHeader = "LLSD/Binary"; 58 * LLSDSerialize
56 59 */
57//static
58const char* LLSDSerialize::LLSDXMLHeader = "LLSD/XML";
59
60// virtual
61LLSDParser::~LLSDParser()
62{ }
63
64// virtual
65LLSDNotationParser::~LLSDNotationParser()
66{ }
67
68 60
69// static 61// static
70void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options) 62void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options)
@@ -74,12 +66,12 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
74 switch (type) 66 switch (type)
75 { 67 {
76 case LLSD_BINARY: 68 case LLSD_BINARY:
77 str << "<? " << LLSDBinaryHeader << " ?>\n"; 69 str << "<? " << LLSD_BINARY_HEADER << " ?>\n";
78 f = new LLSDBinaryFormatter; 70 f = new LLSDBinaryFormatter;
79 break; 71 break;
80 72
81 case LLSD_XML: 73 case LLSD_XML:
82 str << "<? " << LLSDXMLHeader << " ?>\n"; 74 str << "<? " << LLSD_XML_HEADER << " ?>\n";
83 f = new LLSDXMLFormatter; 75 f = new LLSDXMLFormatter;
84 break; 76 break;
85 77
@@ -94,7 +86,7 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
94} 86}
95 87
96// static 88// static
97bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str) 89bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
98{ 90{
99 LLPointer<LLSDParser> p = NULL; 91 LLPointer<LLSDParser> p = NULL;
100 char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */ 92 char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
@@ -102,8 +94,8 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str)
102 int inbuf = 0; 94 int inbuf = 0;
103 bool legacy_no_header = false; 95 bool legacy_no_header = false;
104 bool fail_if_not_legacy = false; 96 bool fail_if_not_legacy = false;
105 std::string header = ""; 97 std::string header;
106 98
107 /* 99 /*
108 * Get the first line before anything. 100 * Get the first line before anything.
109 */ 101 */
@@ -155,15 +147,15 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str)
155 */ 147 */
156 if (legacy_no_header) 148 if (legacy_no_header)
157 { 149 {
158 LLSDXMLParser *x = new LLSDXMLParser; 150 LLSDXMLParser* x = new LLSDXMLParser;
159 x->parsePart(hdr_buf, inbuf); 151 x->parsePart(hdr_buf, inbuf);
160 p = x; 152 p = x;
161 } 153 }
162 else if (header == LLSDBinaryHeader) 154 else if (header == LLSD_BINARY_HEADER)
163 { 155 {
164 p = new LLSDBinaryParser; 156 p = new LLSDBinaryParser;
165 } 157 }
166 else if (header == LLSDXMLHeader) 158 else if (header == LLSD_XML_HEADER)
167 { 159 {
168 p = new LLSDXMLParser; 160 p = new LLSDXMLParser;
169 } 161 }
@@ -174,7 +166,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str)
174 166
175 if (p.notNull()) 167 if (p.notNull())
176 { 168 {
177 p->parse(str, sd); 169 p->parse(str, sd, max_bytes);
178 return true; 170 return true;
179 } 171 }
180 172
@@ -230,11 +222,71 @@ F64 ll_ntohd(F64 netdouble)
230/** 222/**
231 * Local functions. 223 * Local functions.
232 */ 224 */
233bool deserialize_string(std::istream& str, std::string& value); 225/**
234bool deserialize_string_delim(std::istream& str, std::string& value, char d); 226 * @brief Figure out what kind of string it is (raw or delimited) and handoff.
235bool deserialize_string_raw(std::istream& str, std::string& value); 227 *
228 * @param istr The stream to read from.
229 * @param value [out] The string which was found.
230 * @param max_bytes The maximum possible length of the string. Passing in
231 * a negative value will skip this check.
232 * @return Returns number of bytes read off of the stream. Returns
233 * PARSE_FAILURE (-1) on failure.
234 */
235int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes);
236
237/**
238 * @brief Parse a delimited string.
239 *
240 * @param istr The stream to read from, with the delimiter already popped.
241 * @param value [out] The string which was found.
242 * @param d The delimiter to use.
243 * @return Returns number of bytes read off of the stream. Returns
244 * PARSE_FAILURE (-1) on failure.
245 */
246int deserialize_string_delim(std::istream& istr, std::string& value, char d);
247
248/**
249 * @brief Read a raw string off the stream.
250 *
251 * @param istr The stream to read from, with the (len) parameter
252 * leading the stream.
253 * @param value [out] The string which was found.
254 * @param d The delimiter to use.
255 * @param max_bytes The maximum possible length of the string. Passing in
256 * a negative value will skip this check.
257 * @return Returns number of bytes read off of the stream. Returns
258 * PARSE_FAILURE (-1) on failure.
259 */
260int deserialize_string_raw(
261 std::istream& istr,
262 std::string& value,
263 S32 max_bytes);
264
265/**
266 * @brief helper method for dealing with the different notation boolean format.
267 *
268 * @param istr The stream to read from with the leading character stripped.
269 * @param data [out] the result of the parse.
270 * @param compare The string to compare the boolean against
271 * @param vale The value to assign to data if the parse succeeds.
272 * @return Returns number of bytes read off of the stream. Returns
273 * PARSE_FAILURE (-1) on failure.
274 */
275int deserialize_boolean(
276 std::istream& istr,
277 LLSD& data,
278 const std::string& compare,
279 bool value);
280
281/**
282 * @brief Do notation escaping of a string to an ostream.
283 *
284 * @param value The string to escape and serialize
285 * @param str The stream to serialize to.
286 */
236void serialize_string(const std::string& value, std::ostream& str); 287void serialize_string(const std::string& value, std::ostream& str);
237 288
289
238/** 290/**
239 * Local constants. 291 * Local constants.
240 */ 292 */
@@ -244,20 +296,96 @@ static const std::string NOTATION_FALSE_SERIAL("false");
244static const char BINARY_TRUE_SERIAL = '1'; 296static const char BINARY_TRUE_SERIAL = '1';
245static const char BINARY_FALSE_SERIAL = '0'; 297static const char BINARY_FALSE_SERIAL = '0';
246 298
247static const S32 NOTATION_PARSE_FAILURE = -1;
248 299
249/** 300/**
250 * LLSDParser 301 * LLSDParser
251 */ 302 */
252LLSDParser::LLSDParser() 303LLSDParser::LLSDParser() : mCheckLimits(true), mMaxBytesLeft(0)
304{
305}
306
307// virtual
308LLSDParser::~LLSDParser()
309{ }
310
311S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes)
312{
313 mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
314 mMaxBytesLeft = max_bytes;
315 return doParse(istr, data);
316}
317
318
319int LLSDParser::get(std::istream& istr) const
320{
321 if(mCheckLimits) --mMaxBytesLeft;
322 return istr.get();
323}
324
325std::istream& LLSDParser::get(
326 std::istream& istr,
327 char* s,
328 std::streamsize n,
329 char delim) const
330{
331 istr.get(s, n, delim);
332 if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
333 return istr;
334}
335
336std::istream& LLSDParser::get(
337 std::istream& istr,
338 std::streambuf& sb,
339 char delim) const
340{
341 istr.get(sb, delim);
342 if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
343 return istr;
344}
345
346std::istream& LLSDParser::ignore(std::istream& istr) const
253{ 347{
348 istr.ignore();
349 if(mCheckLimits) --mMaxBytesLeft;
350 return istr;
254} 351}
255 352
353std::istream& LLSDParser::putback(std::istream& istr, char c) const
354{
355 istr.putback(c);
356 if(mCheckLimits) ++mMaxBytesLeft;
357 return istr;
358}
359
360std::istream& LLSDParser::read(
361 std::istream& istr,
362 char* s,
363 std::streamsize n) const
364{
365 istr.read(s, n);
366 if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
367 return istr;
368}
369
370void LLSDParser::account(S32 bytes) const
371{
372 if(mCheckLimits) mMaxBytesLeft -= bytes;
373}
374
375
256/** 376/**
257 * LLSDNotationParser 377 * LLSDNotationParser
258 */ 378 */
379LLSDNotationParser::LLSDNotationParser()
380{
381}
382
383// virtual
384LLSDNotationParser::~LLSDNotationParser()
385{ }
386
259// virtual 387// virtual
260S32 LLSDNotationParser::parse(std::istream& istr, LLSD& data) const 388S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
261{ 389{
262 // map: { string:object, string:object } 390 // map: { string:object, string:object }
263 // array: [ object, object, object ] 391 // array: [ object, object, object ]
@@ -275,7 +403,7 @@ S32 LLSDNotationParser::parse(std::istream& istr, LLSD& data) const
275 while(isspace(c)) 403 while(isspace(c))
276 { 404 {
277 // pop the whitespace. 405 // pop the whitespace.
278 c = istr.get(); 406 c = get(istr);
279 c = istr.peek(); 407 c = istr.peek();
280 continue; 408 continue;
281 } 409 }
@@ -287,107 +415,142 @@ S32 LLSDNotationParser::parse(std::istream& istr, LLSD& data) const
287 switch(c) 415 switch(c)
288 { 416 {
289 case '{': 417 case '{':
290 parse_count += parseMap(istr, data); 418 {
291 if(istr.fail()) 419 S32 child_count = parseMap(istr, data);
420 if((child_count == PARSE_FAILURE) || data.isUndefined())
292 { 421 {
293 llinfos << "STREAM FAILURE reading map." << llendl; 422 parse_count = PARSE_FAILURE;
294 } 423 }
295 if(data.isUndefined()) 424 else
296 { 425 {
297 parse_count = NOTATION_PARSE_FAILURE; 426 parse_count += child_count;
427 }
428 if(istr.fail())
429 {
430 llinfos << "STREAM FAILURE reading map." << llendl;
431 parse_count = PARSE_FAILURE;
298 } 432 }
299 break; 433 break;
434 }
300 435
301 case '[': 436 case '[':
302 parse_count += parseArray(istr, data); 437 {
303 if(istr.fail()) 438 S32 child_count = parseArray(istr, data);
439 if((child_count == PARSE_FAILURE) || data.isUndefined())
304 { 440 {
305 llinfos << "STREAM FAILURE reading array." << llendl; 441 parse_count = PARSE_FAILURE;
306 } 442 }
307 if(data.isUndefined()) 443 else
308 { 444 {
309 parse_count = NOTATION_PARSE_FAILURE; 445 parse_count += child_count;
446 }
447 if(istr.fail())
448 {
449 llinfos << "STREAM FAILURE reading array." << llendl;
450 parse_count = PARSE_FAILURE;
310 } 451 }
311 break; 452 break;
453 }
312 454
313 case '!': 455 case '!':
314 c = istr.get(); 456 c = get(istr);
315 data.clear(); 457 data.clear();
316 break; 458 break;
317 459
318 case '0': 460 case '0':
319 c = istr.get(); 461 c = get(istr);
320 data = false; 462 data = false;
321 break; 463 break;
322 464
323 case 'F': 465 case 'F':
324 case 'f': 466 case 'f':
325 do 467 ignore(istr);
468 c = istr.peek();
469 if(isalpha(c))
326 { 470 {
327 istr.ignore(); 471 int cnt = deserialize_boolean(
328 c = istr.peek(); 472 istr,
329 } while (isalpha(c)); 473 data,
330 data = false; 474 NOTATION_FALSE_SERIAL,
475 false);
476 if(PARSE_FAILURE == cnt) parse_count = cnt;
477 else account(cnt);
478 }
479 else
480 {
481 data = false;
482 }
331 if(istr.fail()) 483 if(istr.fail())
332 { 484 {
333 llinfos << "STREAM FAILURE reading boolean." << llendl; 485 llinfos << "STREAM FAILURE reading boolean." << llendl;
486 parse_count = PARSE_FAILURE;
334 } 487 }
335 break; 488 break;
336 489
337 case '1': 490 case '1':
338 c = istr.get(); 491 c = get(istr);
339 data = true; 492 data = true;
340 break; 493 break;
341 494
342 case 'T': 495 case 'T':
343 case 't': 496 case 't':
344 do 497 ignore(istr);
498 c = istr.peek();
499 if(isalpha(c))
345 { 500 {
346 istr.ignore(); 501 int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true);
347 c = istr.peek(); 502 if(PARSE_FAILURE == cnt) parse_count = cnt;
348 } while (isalpha(c)); 503 else account(cnt);
349 data = true; 504 }
505 else
506 {
507 data = true;
508 }
350 if(istr.fail()) 509 if(istr.fail())
351 { 510 {
352 llinfos << "STREAM FAILURE reading boolean." << llendl; 511 llinfos << "STREAM FAILURE reading boolean." << llendl;
512 parse_count = PARSE_FAILURE;
353 } 513 }
354 break; 514 break;
355 515
356 case 'i': 516 case 'i':
357 { 517 {
358 c = istr.get(); 518 c = get(istr);
359 S32 integer = 0; 519 S32 integer = 0;
360 istr >> integer; 520 istr >> integer;
361 data = integer; 521 data = integer;
362 if(istr.fail()) 522 if(istr.fail())
363 { 523 {
364 llinfos << "STREAM FAILURE reading integer." << llendl; 524 llinfos << "STREAM FAILURE reading integer." << llendl;
525 parse_count = PARSE_FAILURE;
365 } 526 }
366 break; 527 break;
367 } 528 }
368 529
369 case 'r': 530 case 'r':
370 { 531 {
371 c = istr.get(); 532 c = get(istr);
372 F64 real = 0.0; 533 F64 real = 0.0;
373 istr >> real; 534 istr >> real;
374 data = real; 535 data = real;
375 if(istr.fail()) 536 if(istr.fail())
376 { 537 {
377 llinfos << "STREAM FAILURE reading real." << llendl; 538 llinfos << "STREAM FAILURE reading real." << llendl;
539 parse_count = PARSE_FAILURE;
378 } 540 }
379 break; 541 break;
380 } 542 }
381 543
382 case 'u': 544 case 'u':
383 { 545 {
384 c = istr.get(); 546 c = get(istr);
385 LLUUID id; 547 LLUUID id;
386 istr >> id; 548 istr >> id;
387 data = id; 549 data = id;
388 if(istr.fail()) 550 if(istr.fail())
389 { 551 {
390 llinfos << "STREAM FAILURE reading uuid." << llendl; 552 llinfos << "STREAM FAILURE reading uuid." << llendl;
553 parse_count = PARSE_FAILURE;
391 } 554 }
392 break; 555 break;
393 } 556 }
@@ -395,126 +558,144 @@ S32 LLSDNotationParser::parse(std::istream& istr, LLSD& data) const
395 case '\"': 558 case '\"':
396 case '\'': 559 case '\'':
397 case 's': 560 case 's':
398 parseString(istr, data); 561 if(!parseString(istr, data))
399 if(istr.fail())
400 { 562 {
401 llinfos << "STREAM FAILURE reading string." << llendl; 563 parse_count = PARSE_FAILURE;
402 } 564 }
403 if(data.isUndefined()) 565 if(istr.fail())
404 { 566 {
405 parse_count = NOTATION_PARSE_FAILURE; 567 llinfos << "STREAM FAILURE reading string." << llendl;
568 parse_count = PARSE_FAILURE;
406 } 569 }
407 break; 570 break;
408 571
409 case 'l': 572 case 'l':
410 { 573 {
411 c = istr.get(); // pop the 'l' 574 c = get(istr); // pop the 'l'
412 c = istr.get(); // pop the delimiter 575 c = get(istr); // pop the delimiter
413 std::string str; 576 std::string str;
414 deserialize_string_delim(istr, str, c); 577 int cnt = deserialize_string_delim(istr, str, c);
415 data = LLURI(str); 578 if(PARSE_FAILURE == cnt)
579 {
580 parse_count = PARSE_FAILURE;
581 }
582 else
583 {
584 data = LLURI(str);
585 account(cnt);
586 }
416 if(istr.fail()) 587 if(istr.fail())
417 { 588 {
418 llinfos << "STREAM FAILURE reading link." << llendl; 589 llinfos << "STREAM FAILURE reading link." << llendl;
590 parse_count = PARSE_FAILURE;
419 } 591 }
420 break; 592 break;
421 } 593 }
422 594
423 case 'd': 595 case 'd':
424 { 596 {
425 c = istr.get(); // pop the 'd' 597 c = get(istr); // pop the 'd'
426 c = istr.get(); // pop the delimiter 598 c = get(istr); // pop the delimiter
427 std::string str; 599 std::string str;
428 deserialize_string_delim(istr, str, c); 600 int cnt = deserialize_string_delim(istr, str, c);
429 data = LLDate(str); 601 if(PARSE_FAILURE == cnt)
602 {
603 parse_count = PARSE_FAILURE;
604 }
605 else
606 {
607 data = LLDate(str);
608 account(cnt);
609 }
430 if(istr.fail()) 610 if(istr.fail())
431 { 611 {
432 llinfos << "STREAM FAILURE reading date." << llendl; 612 llinfos << "STREAM FAILURE reading date." << llendl;
613 parse_count = PARSE_FAILURE;
433 } 614 }
434 break; 615 break;
435 } 616 }
436 617
437 case 'b': 618 case 'b':
438 parseBinary(istr, data); 619 if(!parseBinary(istr, data))
439 if(istr.fail())
440 { 620 {
441 llinfos << "STREAM FAILURE reading data." << llendl; 621 parse_count = PARSE_FAILURE;
442 } 622 }
443 if(data.isUndefined()) 623 if(istr.fail())
444 { 624 {
445 parse_count = NOTATION_PARSE_FAILURE; 625 llinfos << "STREAM FAILURE reading data." << llendl;
626 parse_count = PARSE_FAILURE;
446 } 627 }
447 break; 628 break;
448 629
449 default: 630 default:
450 data.clear(); 631 parse_count = PARSE_FAILURE;
451 parse_count = NOTATION_PARSE_FAILURE;
452 llinfos << "Unrecognized character while parsing: int(" << (int)c 632 llinfos << "Unrecognized character while parsing: int(" << (int)c
453 << ")" << llendl; 633 << ")" << llendl;
454 break; 634 break;
455 } 635 }
636 if(PARSE_FAILURE == parse_count)
637 {
638 data.clear();
639 }
456 return parse_count; 640 return parse_count;
457} 641}
458 642
459// static
460LLSD LLSDNotationParser::parse(std::istream& istr)
461{
462 LLSDNotationParser parser;
463 LLSD rv;
464 S32 count = parser.parse(istr, rv);
465 lldebugs << "LLSDNotationParser::parse parsed " << count << " objects."
466 << llendl;
467 return rv;
468}
469
470S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const 643S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
471{ 644{
472 // map: { string:object, string:object } 645 // map: { string:object, string:object }
473 map = LLSD::emptyMap(); 646 map = LLSD::emptyMap();
474 S32 parse_count = 0; 647 S32 parse_count = 0;
475 char c = istr.get(); 648 char c = get(istr);
476 if(c == '{') 649 if(c == '{')
477 { 650 {
478 // eat commas, white 651 // eat commas, white
479 bool found_name = false; 652 bool found_name = false;
480 std::string name; 653 std::string name;
481 c = istr.get(); 654 c = get(istr);
482 while(c != '}' && istr.good()) 655 while(c != '}' && istr.good())
483 { 656 {
484 if(!found_name) 657 if(!found_name)
485 { 658 {
486 if((c == '\"') || (c == '\'') || (c == 's')) 659 if((c == '\"') || (c == '\'') || (c == 's'))
487 { 660 {
488 istr.putback(c); 661 putback(istr, c);
489 found_name = true; 662 found_name = true;
490 deserialize_string(istr, name); 663 int count = deserialize_string(istr, name, mMaxBytesLeft);
664 if(PARSE_FAILURE == count) return PARSE_FAILURE;
665 account(count);
491 } 666 }
492 c = istr.get(); 667 c = get(istr);
493 } 668 }
494 else 669 else
495 { 670 {
496 if(isspace(c) || (c == ':')) 671 if(isspace(c) || (c == ':'))
497 { 672 {
498 c = istr.get(); 673 c = get(istr);
499 continue; 674 continue;
500 } 675 }
501 istr.putback(c); 676 putback(istr, c);
502 LLSD child; 677 LLSD child;
503 S32 count = parse(istr, child); 678 S32 count = doParse(istr, child);
504 if(count > 0) 679 if(count > 0)
505 { 680 {
681 // There must be a value for every key, thus
682 // child_count must be greater than 0.
506 parse_count += count; 683 parse_count += count;
507 map.insert(name, child); 684 map.insert(name, child);
508 } 685 }
509 else 686 else
510 { 687 {
511 map.clear(); 688 return PARSE_FAILURE;
512 return NOTATION_PARSE_FAILURE;
513 } 689 }
514 found_name = false; 690 found_name = false;
515 c = istr.get(); 691 c = get(istr);
516 } 692 }
517 } 693 }
694 if(c != '}')
695 {
696 map.clear();
697 return PARSE_FAILURE;
698 }
518 } 699 }
519 return parse_count; 700 return parse_count;
520} 701}
@@ -524,52 +705,51 @@ S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const
524 // array: [ object, object, object ] 705 // array: [ object, object, object ]
525 array = LLSD::emptyArray(); 706 array = LLSD::emptyArray();
526 S32 parse_count = 0; 707 S32 parse_count = 0;
527 char c = istr.get(); 708 char c = get(istr);
528 if(c == '[') 709 if(c == '[')
529 { 710 {
530 // eat commas, white 711 // eat commas, white
531 c = istr.get(); 712 c = get(istr);
532 while((c != ']') && istr.good()) 713 while((c != ']') && istr.good())
533 { 714 {
534 LLSD child; 715 LLSD child;
535 if(isspace(c) || (c == ',')) 716 if(isspace(c) || (c == ','))
536 { 717 {
537 c = istr.get(); 718 c = get(istr);
538 continue; 719 continue;
539 } 720 }
540 istr.putback(c); 721 putback(istr, c);
541 S32 count = parse(istr, child); 722 S32 count = doParse(istr, child);
542 if(count > 0) 723 if(PARSE_FAILURE == count)
543 { 724 {
544 parse_count += count; 725 return PARSE_FAILURE;
545 array.append(child);
546 } 726 }
547 else 727 else
548 { 728 {
549 array.clear(); 729 parse_count += count;
550 return NOTATION_PARSE_FAILURE; 730 array.append(child);
551 } 731 }
552 c = istr.get(); 732 c = get(istr);
733 }
734 if(c != ']')
735 {
736 return PARSE_FAILURE;
553 } 737 }
554 } 738 }
555 return parse_count; 739 return parse_count;
556} 740}
557 741
558void LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const 742bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
559{ 743{
560 std::string value; 744 std::string value;
561 if(deserialize_string(istr, value)) 745 int count = deserialize_string(istr, value, mMaxBytesLeft);
562 { 746 if(PARSE_FAILURE == count) return false;
563 data = value; 747 account(count);
564 } 748 data = value;
565 else 749 return true;
566 {
567 // failed to parse.
568 data.clear();
569 }
570} 750}
571 751
572void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const 752bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
573{ 753{
574 // binary: b##"ff3120ab1" 754 // binary: b##"ff3120ab1"
575 // or: b(len)"..." 755 // or: b(len)"..."
@@ -582,40 +762,44 @@ void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
582 762
583 // need to read the base out. 763 // need to read the base out.
584 char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */ 764 char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */
585 istr.get(buf, STREAM_GET_COUNT, '"'); 765 get(istr, buf, STREAM_GET_COUNT, '"');
586 char c = istr.get(); 766 char c = get(istr);
587 if((c == '"') && (0 == strncmp("b(", buf, 2))) 767 if(c != '"') return false;
768 if(0 == strncmp("b(", buf, 2))
588 { 769 {
589 // We probably have a valid raw binary stream. determine 770 // We probably have a valid raw binary stream. determine
590 // the size, and read it. 771 // the size, and read it.
591 // *FIX: Should we set a maximum size?
592 S32 len = strtol(buf + 2, NULL, 0); 772 S32 len = strtol(buf + 2, NULL, 0);
773 if(mCheckLimits && (len > mMaxBytesLeft)) return false;
593 std::vector<U8> value; 774 std::vector<U8> value;
594 if(len) 775 if(len)
595 { 776 {
596 value.resize(len); 777 value.resize(len);
597 fullread(istr, (char *)&value[0], len); 778 account(fullread(istr, (char *)&value[0], len));
598 } 779 }
599 c = istr.get(); // strip off the trailing double-quote 780 c = get(istr); // strip off the trailing double-quote
600 data = value; 781 data = value;
601 } 782 }
602 else if((c == '"') && (0 == strncmp("b64", buf, 3))) 783 else if(0 == strncmp("b64", buf, 3))
603 { 784 {
604 // *FIX: A bit inefficient, but works for now. To make the 785 // *FIX: A bit inefficient, but works for now. To make the
605 // format better, I would need to add a hint into the 786 // format better, I would need to add a hint into the
606 // serialization format that indicated how long it was. 787 // serialization format that indicated how long it was.
607 std::stringstream coded_stream; 788 std::stringstream coded_stream;
608 istr.get(*(coded_stream.rdbuf()), '\"'); 789 get(istr, *(coded_stream.rdbuf()), '\"');
609 c = istr.get(); 790 c = get(istr);
610 std::string encoded(coded_stream.str()); 791 std::string encoded(coded_stream.str());
611 S32 len = apr_base64_decode_len(encoded.c_str()); 792 S32 len = apr_base64_decode_len(encoded.c_str());
612 std::vector<U8> value; 793 std::vector<U8> value;
613 value.resize(len); 794 if(len)
614 len = apr_base64_decode_binary(&value[0], encoded.c_str()); 795 {
615 value.resize(len); 796 value.resize(len);
797 len = apr_base64_decode_binary(&value[0], encoded.c_str());
798 value.resize(len);
799 }
616 data = value; 800 data = value;
617 } 801 }
618 else if((c == '"') && (0 == strncmp("b16", buf, 3))) 802 else if(0 == strncmp("b16", buf, 3))
619 { 803 {
620 // yay, base 16. We pop the next character which is either a 804 // yay, base 16. We pop the next character which is either a
621 // double quote or base 16 data. If it's a double quote, we're 805 // double quote or base 16 data. If it's a double quote, we're
@@ -626,14 +810,14 @@ void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
626 U8 byte_buffer[BINARY_BUFFER_SIZE]; 810 U8 byte_buffer[BINARY_BUFFER_SIZE];
627 U8* write; 811 U8* write;
628 std::vector<U8> value; 812 std::vector<U8> value;
629 c = istr.get(); 813 c = get(istr);
630 while(c != '"') 814 while(c != '"')
631 { 815 {
632 istr.putback(c); 816 putback(istr, c);
633 read = buf; 817 read = buf;
634 write = byte_buffer; 818 write = byte_buffer;
635 istr.get(buf, STREAM_GET_COUNT, '"'); 819 get(istr, buf, STREAM_GET_COUNT, '"');
636 c = istr.get(); 820 c = get(istr);
637 while(*read != '\0') /*Flawfinder: ignore*/ 821 while(*read != '\0') /*Flawfinder: ignore*/
638 { 822 {
639 byte = hex_as_nybble(*read++); 823 byte = hex_as_nybble(*read++);
@@ -648,8 +832,9 @@ void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
648 } 832 }
649 else 833 else
650 { 834 {
651 data.clear(); 835 return false;
652 } 836 }
837 return true;
653} 838}
654 839
655 840
@@ -666,7 +851,7 @@ LLSDBinaryParser::~LLSDBinaryParser()
666} 851}
667 852
668// virtual 853// virtual
669S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const 854S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
670{ 855{
671/** 856/**
672 * Undefined: '!'<br> 857 * Undefined: '!'<br>
@@ -685,7 +870,7 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
685 * notation format. 870 * notation format.
686 */ 871 */
687 char c; 872 char c;
688 c = istr.get(); 873 c = get(istr);
689 if(!istr.good()) 874 if(!istr.good())
690 { 875 {
691 return 0; 876 return 0;
@@ -694,20 +879,42 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
694 switch(c) 879 switch(c)
695 { 880 {
696 case '{': 881 case '{':
697 parse_count += parseMap(istr, data); 882 {
883 S32 child_count = parseMap(istr, data);
884 if((child_count == PARSE_FAILURE) || data.isUndefined())
885 {
886 parse_count = PARSE_FAILURE;
887 }
888 else
889 {
890 parse_count += child_count;
891 }
698 if(istr.fail()) 892 if(istr.fail())
699 { 893 {
700 llinfos << "STREAM FAILURE reading binary map." << llendl; 894 llinfos << "STREAM FAILURE reading binary map." << llendl;
895 parse_count = PARSE_FAILURE;
701 } 896 }
702 break; 897 break;
898 }
703 899
704 case '[': 900 case '[':
705 parse_count += parseArray(istr, data); 901 {
902 S32 child_count = parseArray(istr, data);
903 if((child_count == PARSE_FAILURE) || data.isUndefined())
904 {
905 parse_count = PARSE_FAILURE;
906 }
907 else
908 {
909 parse_count += child_count;
910 }
706 if(istr.fail()) 911 if(istr.fail())
707 { 912 {
708 llinfos << "STREAM FAILURE reading binary array." << llendl; 913 llinfos << "STREAM FAILURE reading binary array." << llendl;
914 parse_count = PARSE_FAILURE;
709 } 915 }
710 break; 916 break;
917 }
711 918
712 case '!': 919 case '!':
713 data.clear(); 920 data.clear();
@@ -724,7 +931,7 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
724 case 'i': 931 case 'i':
725 { 932 {
726 U32 value_nbo = 0; 933 U32 value_nbo = 0;
727 istr.read((char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ 934 read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
728 data = (S32)ntohl(value_nbo); 935 data = (S32)ntohl(value_nbo);
729 if(istr.fail()) 936 if(istr.fail())
730 { 937 {
@@ -736,7 +943,7 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
736 case 'r': 943 case 'r':
737 { 944 {
738 F64 real_nbo = 0.0; 945 F64 real_nbo = 0.0;
739 istr.read((char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/ 946 read(istr, (char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/
740 data = ll_ntohd(real_nbo); 947 data = ll_ntohd(real_nbo);
741 if(istr.fail()) 948 if(istr.fail())
742 { 949 {
@@ -748,7 +955,7 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
748 case 'u': 955 case 'u':
749 { 956 {
750 LLUUID id; 957 LLUUID id;
751 istr.read((char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/ 958 read(istr, (char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/
752 data = id; 959 data = id;
753 if(istr.fail()) 960 if(istr.fail())
754 { 961 {
@@ -761,19 +968,40 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
761 case '"': 968 case '"':
762 { 969 {
763 std::string value; 970 std::string value;
764 deserialize_string_delim(istr, value, c); 971 int cnt = deserialize_string_delim(istr, value, c);
765 data = value; 972 if(PARSE_FAILURE == cnt)
973 {
974 parse_count = PARSE_FAILURE;
975 }
976 else
977 {
978 data = value;
979 account(cnt);
980 }
981 if(istr.fail())
982 {
983 llinfos << "STREAM FAILURE reading binary (notation-style) string."
984 << llendl;
985 parse_count = PARSE_FAILURE;
986 }
766 break; 987 break;
767 } 988 }
768 989
769 case 's': 990 case 's':
770 { 991 {
771 std::string value; 992 std::string value;
772 parseString(istr, value); 993 if(parseString(istr, value))
773 data = value; 994 {
995 data = value;
996 }
997 else
998 {
999 parse_count = PARSE_FAILURE;
1000 }
774 if(istr.fail()) 1001 if(istr.fail())
775 { 1002 {
776 llinfos << "STREAM FAILURE reading binary string." << llendl; 1003 llinfos << "STREAM FAILURE reading binary string." << llendl;
1004 parse_count = PARSE_FAILURE;
777 } 1005 }
778 break; 1006 break;
779 } 1007 }
@@ -781,11 +1009,18 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
781 case 'l': 1009 case 'l':
782 { 1010 {
783 std::string value; 1011 std::string value;
784 parseString(istr, value); 1012 if(parseString(istr, value))
785 data = LLURI(value); 1013 {
1014 data = LLURI(value);
1015 }
1016 else
1017 {
1018 parse_count = PARSE_FAILURE;
1019 }
786 if(istr.fail()) 1020 if(istr.fail())
787 { 1021 {
788 llinfos << "STREAM FAILURE reading binary link." << llendl; 1022 llinfos << "STREAM FAILURE reading binary link." << llendl;
1023 parse_count = PARSE_FAILURE;
789 } 1024 }
790 break; 1025 break;
791 } 1026 }
@@ -793,11 +1028,12 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
793 case 'd': 1028 case 'd':
794 { 1029 {
795 F64 real = 0.0; 1030 F64 real = 0.0;
796 istr.read((char*)&real, sizeof(F64)); /*Flawfinder: ignore*/ 1031 read(istr, (char*)&real, sizeof(F64)); /*Flawfinder: ignore*/
797 data = LLDate(real); 1032 data = LLDate(real);
798 if(istr.fail()) 1033 if(istr.fail())
799 { 1034 {
800 llinfos << "STREAM FAILURE reading binary date." << llendl; 1035 llinfos << "STREAM FAILURE reading binary date." << llendl;
1036 parse_count = PARSE_FAILURE;
801 } 1037 }
802 break; 1038 break;
803 } 1039 }
@@ -806,75 +1042,94 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
806 { 1042 {
807 // We probably have a valid raw binary stream. determine 1043 // We probably have a valid raw binary stream. determine
808 // the size, and read it. 1044 // the size, and read it.
809 // *FIX: Should we set a maximum size?
810 U32 size_nbo = 0; 1045 U32 size_nbo = 0;
811 istr.read((char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/ 1046 read(istr, (char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/
812 S32 size = (S32)ntohl(size_nbo); 1047 S32 size = (S32)ntohl(size_nbo);
813 std::vector<U8> value; 1048 if(mCheckLimits && (size > mMaxBytesLeft))
814 if(size)
815 { 1049 {
816 value.resize(size); 1050 parse_count = PARSE_FAILURE;
817 istr.read((char*)&value[0], size); /*Flawfinder: ignore*/ 1051 }
1052 else
1053 {
1054 std::vector<U8> value;
1055 if(size > 0)
1056 {
1057 value.resize(size);
1058 account(fullread(istr, (char*)&value[0], size));
1059 }
1060 data = value;
818 } 1061 }
819 data = value;
820 if(istr.fail()) 1062 if(istr.fail())
821 { 1063 {
822 llinfos << "STREAM FAILURE reading binary." << llendl; 1064 llinfos << "STREAM FAILURE reading binary." << llendl;
1065 parse_count = PARSE_FAILURE;
823 } 1066 }
824 break; 1067 break;
825 } 1068 }
826 1069
827 default: 1070 default:
828 --parse_count; 1071 parse_count = PARSE_FAILURE;
829 llinfos << "Unrecognized character while parsing: int(" << (int)c 1072 llinfos << "Unrecognized character while parsing: int(" << (int)c
830 << ")" << llendl; 1073 << ")" << llendl;
831 break; 1074 break;
832 } 1075 }
1076 if(PARSE_FAILURE == parse_count)
1077 {
1078 data.clear();
1079 }
833 return parse_count; 1080 return parse_count;
834} 1081}
835 1082
836// static
837LLSD LLSDBinaryParser::parse(std::istream& istr)
838{
839 LLSDBinaryParser parser;
840 LLSD rv;
841 S32 count = parser.parse(istr, rv);
842 lldebugs << "LLSDBinaryParser::parse parsed " << count << " objects."
843 << llendl;
844 return rv;
845}
846
847S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const 1083S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
848{ 1084{
849 map = LLSD::emptyMap(); 1085 map = LLSD::emptyMap();
850 U32 value_nbo = 0; 1086 U32 value_nbo = 0;
851 istr.read((char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ 1087 read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
852 S32 size = (S32)ntohl(value_nbo); 1088 S32 size = (S32)ntohl(value_nbo);
853 S32 parse_count = 0; 1089 S32 parse_count = 0;
854 S32 count = 0; 1090 S32 count = 0;
855 char c = istr.get(); 1091 char c = get(istr);
856 while(c != '}' && (count < size) && istr.good()) 1092 while(c != '}' && (count < size) && istr.good())
857 { 1093 {
858 std::string name; 1094 std::string name;
859 switch(c) 1095 switch(c)
860 { 1096 {
861 case 'k': 1097 case 'k':
862 parseString(istr, name); 1098 if(!parseString(istr, name))
1099 {
1100 return PARSE_FAILURE;
1101 }
863 break; 1102 break;
864 case '\'': 1103 case '\'':
865 case '"': 1104 case '"':
866 deserialize_string_delim(istr, name, c); 1105 {
1106 int cnt = deserialize_string_delim(istr, name, c);
1107 if(PARSE_FAILURE == cnt) return PARSE_FAILURE;
1108 account(cnt);
867 break; 1109 break;
868 } 1110 }
1111 }
869 LLSD child; 1112 LLSD child;
870 S32 child_count = parse(istr, child); 1113 S32 child_count = doParse(istr, child);
871 if(child_count) 1114 if(child_count > 0)
872 { 1115 {
1116 // There must be a value for every key, thus child_count
1117 // must be greater than 0.
873 parse_count += child_count; 1118 parse_count += child_count;
874 map.insert(name, child); 1119 map.insert(name, child);
875 } 1120 }
1121 else
1122 {
1123 return PARSE_FAILURE;
1124 }
876 ++count; 1125 ++count;
877 c = istr.get(); 1126 c = get(istr);
1127 }
1128 if((c != '}') || (count < size))
1129 {
1130 // Make sure it is correctly terminated and we parsed as many
1131 // as were said to be there.
1132 return PARSE_FAILURE;
878 } 1133 }
879 return parse_count; 1134 return parse_count;
880} 1135}
@@ -883,7 +1138,7 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
883{ 1138{
884 array = LLSD::emptyArray(); 1139 array = LLSD::emptyArray();
885 U32 value_nbo = 0; 1140 U32 value_nbo = 0;
886 istr.read((char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ 1141 read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
887 S32 size = (S32)ntohl(value_nbo); 1142 S32 size = (S32)ntohl(value_nbo);
888 1143
889 // *FIX: This would be a good place to reserve some space in the 1144 // *FIX: This would be a good place to reserve some space in the
@@ -895,7 +1150,11 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
895 while((c != ']') && (count < size) && istr.good()) 1150 while((c != ']') && (count < size) && istr.good())
896 { 1151 {
897 LLSD child; 1152 LLSD child;
898 S32 child_count = parse(istr, child); 1153 S32 child_count = doParse(istr, child);
1154 if(PARSE_FAILURE == child_count)
1155 {
1156 return PARSE_FAILURE;
1157 }
899 if(child_count) 1158 if(child_count)
900 { 1159 {
901 parse_count += child_count; 1160 parse_count += child_count;
@@ -904,22 +1163,33 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
904 ++count; 1163 ++count;
905 c = istr.peek(); 1164 c = istr.peek();
906 } 1165 }
907 c = istr.get(); 1166 c = get(istr);
1167 if((c != ']') || (count < size))
1168 {
1169 // Make sure it is correctly terminated and we parsed as many
1170 // as were said to be there.
1171 return PARSE_FAILURE;
1172 }
908 return parse_count; 1173 return parse_count;
909} 1174}
910 1175
911void LLSDBinaryParser::parseString( 1176bool LLSDBinaryParser::parseString(
912 std::istream& istr, 1177 std::istream& istr,
913 std::string& value) const 1178 std::string& value) const
914{ 1179{
915 // *FIX: This is memory inefficient. 1180 // *FIX: This is memory inefficient.
916 U32 value_nbo = 0; 1181 U32 value_nbo = 0;
917 istr.read((char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ 1182 read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
918 S32 size = (S32)ntohl(value_nbo); 1183 S32 size = (S32)ntohl(value_nbo);
1184 if(mCheckLimits && (size > mMaxBytesLeft)) return false;
919 std::vector<char> buf; 1185 std::vector<char> buf;
920 buf.resize(size); 1186 if(size)
921 istr.read(&buf[0], size); /*Flawfinder: ignore*/ 1187 {
922 value.assign(buf.begin(), buf.end()); 1188 buf.resize(size);
1189 account(fullread(istr, &buf[0], size));
1190 value.assign(buf.begin(), buf.end());
1191 }
1192 return true;
923} 1193}
924 1194
925 1195
@@ -1217,33 +1487,38 @@ void LLSDBinaryFormatter::formatString(
1217/** 1487/**
1218 * local functions 1488 * local functions
1219 */ 1489 */
1220bool deserialize_string(std::istream& str, std::string& value) 1490int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes)
1221{ 1491{
1222 char c = str.get(); 1492 char c = istr.get();
1223 if (str.fail()) 1493 if(istr.fail())
1224 { 1494 {
1225 // No data in stream, bail out 1495 // No data in stream, bail out but mention the character we
1226 return false; 1496 // grabbed.
1497 return LLSDParser::PARSE_FAILURE;
1227 } 1498 }
1228 1499
1229 bool rv = false; 1500 int rv = LLSDParser::PARSE_FAILURE;
1230 switch(c) 1501 switch(c)
1231 { 1502 {
1232 case '\'': 1503 case '\'':
1233 case '"': 1504 case '"':
1234 rv = deserialize_string_delim(str, value, c); 1505 rv = deserialize_string_delim(istr, value, c);
1235 break; 1506 break;
1236 case 's': 1507 case 's':
1237 rv = deserialize_string_raw(str, value); 1508 // technically, less than max_bytes, but this is just meant to
1509 // catch egregious protocol errors. parse errors will be
1510 // caught in the case of incorrect counts.
1511 rv = deserialize_string_raw(istr, value, max_bytes);
1238 break; 1512 break;
1239 default: 1513 default:
1240 break; 1514 break;
1241 } 1515 }
1242 return rv; 1516 if(LLSDParser::PARSE_FAILURE == rv) return rv;
1517 return rv + 1; // account for the character grabbed at the top.
1243} 1518}
1244 1519
1245bool deserialize_string_delim( 1520int deserialize_string_delim(
1246 std::istream& str, 1521 std::istream& istr,
1247 std::string& value, 1522 std::string& value,
1248 char delim) 1523 char delim)
1249{ 1524{
@@ -1252,16 +1527,18 @@ bool deserialize_string_delim(
1252 bool found_hex = false; 1527 bool found_hex = false;
1253 bool found_digit = false; 1528 bool found_digit = false;
1254 U8 byte = 0; 1529 U8 byte = 0;
1255 1530 int count = 0;
1531
1256 while (true) 1532 while (true)
1257 { 1533 {
1258 char next_char = str.get(); 1534 char next_char = istr.get();
1259 1535 ++count;
1260 if(str.fail()) 1536
1537 if(istr.fail())
1261 { 1538 {
1262 // If our stream is empty, break out 1539 // If our stream is empty, break out
1263 value = write_buffer.str(); 1540 value = write_buffer.str();
1264 return false; 1541 return LLSDParser::PARSE_FAILURE;
1265 } 1542 }
1266 1543
1267 if(found_escape) 1544 if(found_escape)
@@ -1338,35 +1615,48 @@ bool deserialize_string_delim(
1338 } 1615 }
1339 1616
1340 value = write_buffer.str(); 1617 value = write_buffer.str();
1341 return true; 1618 return count;
1342} 1619}
1343 1620
1344bool deserialize_string_raw(std::istream& str, std::string& value) 1621int deserialize_string_raw(
1622 std::istream& istr,
1623 std::string& value,
1624 S32 max_bytes)
1345{ 1625{
1346 bool ok = false; 1626 int count = 0;
1347 const S32 BUF_LEN = 20; 1627 const S32 BUF_LEN = 20;
1348 char buf[BUF_LEN]; /* Flawfinder: ignore */ 1628 char buf[BUF_LEN]; /* Flawfinder: ignore */
1349 str.get(buf, BUF_LEN - 1, ')'); 1629 istr.get(buf, BUF_LEN - 1, ')');
1350 char c = str.get(); 1630 count += istr.gcount();
1351 c = str.get(); 1631 char c = istr.get();
1632 c = istr.get();
1633 count += 2;
1352 if(((c == '"') || (c == '\'')) && (buf[0] == '(')) 1634 if(((c == '"') || (c == '\'')) && (buf[0] == '('))
1353 { 1635 {
1354 // We probably have a valid raw string. determine 1636 // We probably have a valid raw string. determine
1355 // the size, and read it. 1637 // the size, and read it.
1356 // *FIX: Should we set a maximum size?
1357 // *FIX: This is memory inefficient. 1638 // *FIX: This is memory inefficient.
1358 S32 len = strtol(buf + 1, NULL, 0); 1639 S32 len = strtol(buf + 1, NULL, 0);
1640 if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE;
1359 std::vector<char> buf; 1641 std::vector<char> buf;
1360 buf.resize(len); 1642 if(len)
1361 str.read(&buf[0], len); /*Flawfinder: ignore*/ 1643 {
1362 value.assign(buf.begin(), buf.end()); 1644 buf.resize(len);
1363 c = str.get(); 1645 count += fullread(istr, (char *)&buf[0], len);
1364 if((c == '"') || (c == '\'')) 1646 value.assign(buf.begin(), buf.end());
1647 }
1648 c = istr.get();
1649 ++count;
1650 if(!((c == '"') || (c == '\'')))
1365 { 1651 {
1366 ok = true; 1652 return LLSDParser::PARSE_FAILURE;
1367 } 1653 }
1368 } 1654 }
1369 return ok; 1655 else
1656 {
1657 return LLSDParser::PARSE_FAILURE;
1658 }
1659 return count;
1370} 1660}
1371 1661
1372static const char* NOTATION_STRING_CHARACTERS[256] = 1662static const char* NOTATION_STRING_CHARACTERS[256] =
@@ -1641,6 +1931,43 @@ void serialize_string(const std::string& value, std::ostream& str)
1641 } 1931 }
1642} 1932}
1643 1933
1934int deserialize_boolean(
1935 std::istream& istr,
1936 LLSD& data,
1937 const std::string& compare,
1938 bool value)
1939{
1940 //
1941 // this method is a little goofy, because it gets the stream at
1942 // the point where the t or f has already been
1943 // consumed. Basically, parse for a patch to the string passed in
1944 // starting at index 1. If it's a match:
1945 // * assign data to value
1946 // * return the number of bytes read
1947 // otherwise:
1948 // * set data to LLSD::null
1949 // * return LLSDParser::PARSE_FAILURE (-1)
1950 //
1951 int bytes_read = 0;
1952 std::string::size_type ii = 0;
1953 char c = istr.peek();
1954 while((++ii < compare.size())
1955 && (tolower(c) == (int)compare[ii])
1956 && istr.good())
1957 {
1958 istr.ignore();
1959 ++bytes_read;
1960 c = istr.peek();
1961 }
1962 if(compare.size() != ii)
1963 {
1964 data.clear();
1965 return LLSDParser::PARSE_FAILURE;
1966 }
1967 data = value;
1968 return bytes_read;
1969}
1970
1644std::ostream& operator<<(std::ostream& s, const LLSD& llsd) 1971std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
1645{ 1972{
1646 s << LLSDNotationStreamer(llsd); 1973 s << LLSDNotationStreamer(llsd);