Branch data Line data Source code
1 : : /** @file length.cc
2 : : * @brief length encoded as a string
3 : : */
4 : : /* Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2015 Olly Betts
5 : : *
6 : : * This program is free software; you can redistribute it and/or modify
7 : : * it under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation; either version 2 of the License, or
9 : : * (at your option) any later version.
10 : : *
11 : : * This program is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : * GNU General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with this program; if not, write to the Free Software
18 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : : */
20 : :
21 : : #include <config.h>
22 : :
23 : : #include "length.h"
24 : :
25 : : #ifndef XAPIAN_UNITTEST
26 : :
27 : : #include "xapian/error.h"
28 : :
29 : : [[noreturn]]
30 : : static void
31 : 0 : throw_network_error(const char * msg)
32 : : {
33 [ # # ][ # # ]: 0 : throw Xapian::NetworkError(msg);
[ # # ]
34 : : }
35 : :
36 : : #else
37 : :
38 : : class Xapian_NetworkError {
39 : : const char * msg;
40 : :
41 : : public:
42 : 15 : explicit Xapian_NetworkError(const char * msg_) : msg(msg_) { }
43 : :
44 : : const char * get_description() const { return msg; }
45 : : };
46 : :
47 : : [[noreturn]]
48 : : static void
49 : 15 : throw_network_error(const char * msg)
50 : : {
51 : 15 : throw Xapian_NetworkError(msg);
52 : : }
53 : :
54 : : #endif
55 : :
56 : : template<typename T>
57 : : static inline void
58 : 5964971 : decode_length_(const char ** p, const char *end, T & out)
59 : : {
60 [ # # ][ - + ]: 5964971 : if (*p == end) {
[ - + ]
61 : 0 : throw_network_error("Bad encoded length: no data");
62 : : }
63 : :
64 : 5964971 : T len = static_cast<unsigned char>(*(*p)++);
65 [ # # ][ + + ]: 5964971 : if (len == 0xff) {
[ + + ]
66 : 401126 : len = 0;
67 : : unsigned char ch;
68 : 401126 : unsigned shift = 0;
69 [ # # ][ + + ]: 1109691 : do {
[ + + ]
70 [ # # ][ # # ]: 1109691 : if (*p == end || shift > (sizeof(T) * 8 / 7 * 7))
[ + - ][ - + ]
[ + - ][ - + ]
71 : 0 : throw_network_error("Bad encoded length: insufficient data");
72 : 1109691 : ch = *(*p)++;
73 : 1109691 : len |= T(ch & 0x7f) << shift;
74 : 1109691 : shift += 7;
75 : : } while ((ch & 0x80) == 0);
76 : 401126 : len += 255;
77 : : }
78 : 5964971 : out = len;
79 : 5964971 : }
80 : :
81 : : template<typename T>
82 : : static inline void
83 : 1544380 : decode_length_and_check_(const char ** p, const char *end, T & out)
84 : : {
85 : 1544380 : decode_length(p, end, out);
86 [ # # + + : 1544380 : if (out > T(end - *p)) {
# # ]
87 : 15 : throw_network_error("Bad encoded length: length greater than data");
88 : : }
89 : 1544365 : }
90 : :
91 : : void
92 : 3653156 : decode_length(const char ** p, const char *end, unsigned & out)
93 : : {
94 : 3653156 : decode_length_(p, end, out);
95 : 3653156 : }
96 : :
97 : : void
98 : 2311815 : decode_length(const char ** p, const char *end, unsigned long & out)
99 : : {
100 : 2311815 : decode_length_(p, end, out);
101 : 2311815 : }
102 : :
103 : : void
104 : 0 : decode_length(const char ** p, const char *end, unsigned long long & out)
105 : : {
106 : 0 : decode_length_(p, end, out);
107 : 0 : }
108 : :
109 : : void
110 : 0 : decode_length_and_check(const char ** p, const char *end, unsigned & out)
111 : : {
112 : 0 : decode_length_and_check_(p, end, out);
113 : 0 : }
114 : :
115 : : void
116 : 1544380 : decode_length_and_check(const char ** p, const char *end, unsigned long & out)
117 : : {
118 : 1544380 : decode_length_and_check_(p, end, out);
119 : 1544365 : }
120 : :
121 : : void
122 : 0 : decode_length_and_check(const char ** p, const char *end,
123 : : unsigned long long & out)
124 : : {
125 : 0 : decode_length_and_check_(p, end, out);
126 : 0 : }
|