~zorba-coders/zorba/bug1123835

« back to all changes in this revision

Viewing changes to src/runtime/sequences/unparsed_streambuf.cpp

  • Committer: Juan Zacarias
  • Date: 2013-06-03 20:36:56 UTC
  • Revision ID: juan457@gmail.com-20130603203656-wkecu3fnop82fbod
Modified validation of utf8 in the unparsed-text* functions to detect invalid xml.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#include "unparsed_streambuf.h"
2
 
#include "util/utf8_streambuf.h"
3
2
 
4
3
#include "diagnostics/xquery_diagnostics.h"
5
4
#include "diagnostics/util_macros.h"
 
5
#include "util/oseparator.h"
 
6
 
 
7
#include <iomanip>
6
8
 
7
9
using namespace std;
8
10
 
9
11
namespace zorba {
10
12
namespace unparsed{
 
13
  namespace xml{
 
14
    streambuf::pos_type streambuf::seekoff( off_type o, ios_base::seekdir d, ios_base::openmode m ) 
 
15
    {
 
16
      clear();
 
17
      return original()->pubseekoff( o, d, m );
 
18
    }
 
19
 
 
20
    streambuf::pos_type streambuf::seekpos( pos_type p, ios_base::openmode m ) 
 
21
    {
 
22
      clear();
 
23
      return original()->pubseekpos( p, m );
 
24
    }
 
25
 
 
26
    streambuf::int_type streambuf::pbackfail( int_type c ) 
 
27
    {
 
28
      if ( !traits_type::eq_int_type( c, traits_type::eof() ) &&
 
29
           gbuf_.cur_len_ &&
 
30
           original()->sputbackc( traits_type::to_char_type( c ) ) ) {
 
31
        --gbuf_.cur_len_;
 
32
        return c;
 
33
      }
 
34
      return traits_type::eof();
 
35
    }
 
36
 
 
37
    streambuf::int_type streambuf::uflow() 
 
38
    {
 
39
    #ifdef ZORBA_DEBUG_UTF8_STREAMBUF
 
40
      printf( "uflow()\n" );
 
41
    #endif
 
42
      int_type const c = original()->sbumpc();
 
43
      if ( traits_type::eq_int_type( c, traits_type::eof() ) )
 
44
        return traits_type::eof();
 
45
      gbuf_.validate( traits_type::to_char_type( c ) );
 
46
      return c;
 
47
    }
 
48
 
 
49
    inline void streambuf::clear() {
 
50
      gbuf_.clear();
 
51
    }
 
52
  
 
53
    streamsize streambuf::xsgetn(char_type* to, std::streamsize size )
 
54
    {
 
55
    #ifdef ZORBA_DEBUG_UTF8_STREAMBUF
 
56
      printf( "xsgetn()\n" );
 
57
    #endif
 
58
      streamsize return_size = 0;
 
59
 
 
60
      if ( gbuf_.char_len_ ) {
 
61
        streamsize const want = gbuf_.char_len_ - gbuf_.cur_len_;
 
62
        streamsize const get = min( want, size );
 
63
        streamsize const got = original()->sgetn( to, get );
 
64
        for ( streamsize i = 0; i < got; ++i )
 
65
          gbuf_.validate( to[i] );
 
66
        to += got;
 
67
        size -= got, return_size += got;
 
68
      }
 
69
 
 
70
      while ( size > 0 ) {
 
71
        if ( streamsize const got = original()->sgetn( to, size ) ) {
 
72
          for ( streamsize i = 0; i < got; ++i )
 
73
            gbuf_.validate( to[i] );
 
74
          to += got;
 
75
          size -= got, return_size += got;
 
76
        } else
 
77
          break;
 
78
      }
 
79
      return return_size;
 
80
    }
 
81
 
 
82
    inline void streambuf::buf_type::clear() 
 
83
    {
 
84
      char_len_ = 0;
 
85
    }
 
86
 
 
87
    void streambuf::buf_type::throw_invalid_utf8( utf8::storage_type *buf, utf8::size_type len ) {
 
88
      ostringstream oss;
 
89
      oss << hex << setfill('0') << setw(2) << uppercase;
 
90
      oseparator comma( ',' );
 
91
 
 
92
      for ( utf8::size_type i = 0; i < len; ++i )
 
93
        oss << comma << "0x" << (static_cast<unsigned>( buf[i] ) & 0xFF);
 
94
 
 
95
      clear();
 
96
      throw ZORBA_EXCEPTION(
 
97
        zerr::ZXQD0006_INVALID_UTF8_BYTE_SEQUENCE,
 
98
        ERROR_PARAMS( oss.str() )
 
99
      );
 
100
    }
 
101
 
 
102
    void streambuf::buf_type::validate( utf8::storage_type c, bool bump ) {
 
103
      utf8::size_type char_len_copy = char_len_, cur_len_copy = cur_len_;
 
104
 
 
105
      if ( !char_len_copy ) {
 
106
        //
 
107
        // This means we're (hopefully) at the first byte of a UTF-8 byte sequence
 
108
        // comprising a character.
 
109
        //
 
110
        try {
 
111
          char_len_copy = utf8::char_length( c );
 
112
          cur_len_copy = 0;
 
113
          if (!c)
 
114
            throw_invalid_utf8 ( &c, 1);
 
115
        }
 
116
        catch ( utf8::invalid_byte const& ) {
 
117
          throw_invalid_utf8( &c, 1 );
 
118
        }
 
119
      }
 
120
 
 
121
      utf8::storage_type *const cur_byte_ptr = utf8_char_ + cur_len_copy;
 
122
      utf8::storage_type const old_byte = *cur_byte_ptr;
 
123
      *cur_byte_ptr = c;
 
124
 
 
125
      if ( cur_len_copy++ && !utf8::is_continuation_byte( c ) )
 
126
        throw_invalid_utf8( utf8_char_, cur_len_copy );
 
127
 
 
128
      if ( bump ) {
 
129
        char_len_ = (cur_len_copy == char_len_copy ? 0 : char_len_copy);
 
130
        cur_len_ = cur_len_copy;
 
131
      } else {
 
132
        *cur_byte_ptr = old_byte;
 
133
      }
 
134
    }
 
135
  } //xml namespace
11
136
 
12
137
  streambuf::streambuf(std::streambuf* orig, zstring const& uri, QueryLoc const& loc) :
13
 
    proxy_buf(new utf8::streambuf(orig)), 
 
138
    proxy_buf(new xml::streambuf(orig)), 
14
139
    i_uri(uri),
15
140
    i_loc(loc),
16
141
    i_mark(0)
18
143
  }
19
144
 
20
145
  streambuf::streambuf(std::streambuf* orig, int mark, zstring const& uri, QueryLoc const& loc) :
21
 
    proxy_buf(new utf8::streambuf(orig)), 
 
146
    proxy_buf(new xml::streambuf(orig)), 
22
147
    i_uri(uri),
23
148
    i_loc(loc),
24
149
    i_mark(mark)