ox 1.2.10 → 1.2.11

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ox might be problematic. Click here for more details.

Files changed (4) hide show
  1. data/ext/ox/parse.c +118 -1
  2. data/lib/ox/version.rb +1 -1
  3. data/test/func.rb +7 -0
  4. metadata +2 -2
@@ -41,11 +41,13 @@ static void read_doctype(PInfo pi);
41
41
  static void read_comment(PInfo pi);
42
42
  static void read_element(PInfo pi);
43
43
  static void read_text(PInfo pi);
44
+ //static void read_reduced_text(PInfo pi);
44
45
  static void read_cdata(PInfo pi);
45
46
  static char* read_name_token(PInfo pi);
46
47
  static char* read_quoted_value(PInfo pi);
47
48
  static int read_coded_char(PInfo pi);
48
49
  static void next_non_white(PInfo pi);
50
+ static int collapse_special(char *str);
49
51
 
50
52
  /* This XML parser is a single pass, destructive, callback parser. It is a
51
53
  * single pass parse since it only make one pass over the characters in the
@@ -338,6 +340,11 @@ read_element(PInfo pi) {
338
340
  // read value
339
341
  next_non_white(pi);
340
342
  ap->value = read_quoted_value(pi);
343
+ if (0 != strchr(ap->value, '&')) {
344
+ if (0 != collapse_special((char*)ap->value)) {
345
+ raise_error("invalid format, special character does not end with a semicolon", pi->str, pi->s);
346
+ }
347
+ }
341
348
  ap++;
342
349
  if (MAX_ATTRS <= (ap - attrs)) {
343
350
  raise_error("too many attributes", pi->str, pi->s);
@@ -399,6 +406,8 @@ read_element(PInfo pi) {
399
406
  pi->s = start;
400
407
  //pi->s--;
401
408
  read_text(pi);
409
+ //read_reduced_text(pi);
410
+
402
411
  // to exit read_text with no errors the next character must be <
403
412
  if ('/' == *(pi->s + 1) &&
404
413
  0 == strncmp(ename, pi->s + 2, elen) &&
@@ -415,6 +424,63 @@ read_element(PInfo pi) {
415
424
 
416
425
  static void
417
426
  read_text(PInfo pi) {
427
+ char buf[MAX_TEXT_LEN];
428
+ char *b = buf;
429
+ char *alloc_buf = 0;
430
+ char *end = b + sizeof(buf) - 2;
431
+ char c;
432
+ int done = 0;
433
+
434
+ while (!done) {
435
+ c = *pi->s++;
436
+ switch(c) {
437
+ case '<':
438
+ done = 1;
439
+ pi->s--;
440
+ break;
441
+ case '\0':
442
+ raise_error("invalid format, document not terminated", pi->str, pi->s);
443
+ default:
444
+ if ('&' == c) {
445
+ c = read_coded_char(pi);
446
+ }
447
+ if (end <= b) {
448
+ unsigned long size;
449
+
450
+ if (0 == alloc_buf) {
451
+ size = sizeof(buf) * 2;
452
+ if (0 == (alloc_buf = (char*)malloc(size))) {
453
+ raise_error("text too long", pi->str, pi->s);
454
+ }
455
+ memcpy(alloc_buf, buf, b - buf);
456
+ b = alloc_buf + (b - buf);
457
+ } else {
458
+ unsigned long pos = b - alloc_buf;
459
+
460
+ size = (end - alloc_buf) * 2;
461
+ if (0 == (alloc_buf = (char*)realloc(alloc_buf, size))) {
462
+ raise_error("text too long", pi->str, pi->s);
463
+ }
464
+ b = alloc_buf + pos;
465
+ }
466
+ end = alloc_buf + size - 2;
467
+ }
468
+ *b++ = c;
469
+ break;
470
+ }
471
+ }
472
+ *b = '\0';
473
+ if (0 != alloc_buf) {
474
+ pi->pcb->add_text(pi, alloc_buf, ('/' == *(pi->s + 1)));
475
+ free(alloc_buf);
476
+ } else {
477
+ pi->pcb->add_text(pi, buf, ('/' == *(pi->s + 1)));
478
+ }
479
+ }
480
+
481
+ #if 0
482
+ static void
483
+ read_reduced_text(PInfo pi) {
418
484
  char buf[MAX_TEXT_LEN];
419
485
  char *b = buf;
420
486
  char *alloc_buf = 0;
@@ -480,6 +546,7 @@ read_text(PInfo pi) {
480
546
  pi->pcb->add_text(pi, buf, ('/' == *(pi->s + 1)));
481
547
  }
482
548
  }
549
+ #endif
483
550
 
484
551
  static char*
485
552
  read_name_token(PInfo pi) {
@@ -542,7 +609,7 @@ read_quoted_value(PInfo pi) {
542
609
  for (; *pi->s != '"'; pi->s++) {
543
610
  if ('\0' == *pi->s) {
544
611
  raise_error("invalid format, document not terminated", pi->str, pi->s);
545
- }
612
+ }
546
613
  }
547
614
  *pi->s = '\0'; // terminate value
548
615
  pi->s++; // move past quote
@@ -599,3 +666,53 @@ read_coded_char(PInfo pi) {
599
666
  return *pi->s;
600
667
  }
601
668
 
669
+ static int
670
+ collapse_special(char *str) {
671
+ char *s = str;
672
+ char *b = str;
673
+
674
+ while ('\0' != *s) {
675
+ if ('&' == *s) {
676
+ int c;
677
+ char *end;
678
+
679
+ s++;
680
+ if ('#' == *s) {
681
+ c = (int)strtol(s, &end, 10);
682
+ if (';' != *end) {
683
+ return EDOM;
684
+ }
685
+ s = end + 1;
686
+ } else if (0 == strncasecmp(s, "lt;", 3)) {
687
+ c = '<';
688
+ s += 3;
689
+ } else if (0 == strncasecmp(s, "gt;", 3)) {
690
+ c = '>';
691
+ s += 3;
692
+ } else if (0 == strncasecmp(s, "amp;", 4)) {
693
+ c = '&';
694
+ s += 4;
695
+ } else if (0 == strncasecmp(s, "quot;", 5)) {
696
+ c = '"';
697
+ s += 5;
698
+ } else if (0 == strncasecmp(s, "apos;", 5)) {
699
+ c = '\'';
700
+ s += 5;
701
+ } else {
702
+ c = '?';
703
+ while (';' != *s++) {
704
+ if ('\0' == *s) {
705
+ return EDOM;
706
+ }
707
+ }
708
+ s++;
709
+ }
710
+ *b++ = (char)c;
711
+ } else {
712
+ *b++ = *s++;
713
+ }
714
+ }
715
+ *b = '\0';
716
+
717
+ return 0;
718
+ }
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Ox
3
3
  # Current version of the module.
4
- VERSION = '1.2.10'
4
+ VERSION = '1.2.11'
5
5
  end
@@ -223,6 +223,13 @@ class Func < ::Test::Unit::TestCase
223
223
  dump_and_load(s.new(2, 4, 10, 20), false)
224
224
  end
225
225
 
226
+ def test_bad_format
227
+ xml = "<?xml version=\"1.0\"?>\n<tag>test</tagz>\n"
228
+ assert_raise(EncodingError) {
229
+ Ox.load(xml, :mode => :generic, :trace => 0)
230
+ }
231
+ end
232
+
226
233
  def test_array_multi
227
234
  dump_and_load([nil, true, false, 3, 'z', 7.9, 'a&b', :xyz, Time.now, (-1..7)], false)
228
235
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ox
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.2.10
5
+ version: 1.2.11
6
6
  platform: ruby
7
7
  authors:
8
8
  - Peter Ohler
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-08-29 00:00:00 +09:00
13
+ date: 2011-08-30 00:00:00 +09:00
14
14
  default_executable:
15
15
  dependencies: []
16
16