Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include <cassert>
23 : #include <cstdlib>
24 : #include <new>
25 : #include <vector>
26 :
27 : #include "boost/noncopyable.hpp"
28 : #include "com/sun/star/io/IOException.hpp"
29 : #include "com/sun/star/uno/Reference.hxx"
30 : #include "com/sun/star/uno/RuntimeException.hpp"
31 : #include "com/sun/star/uno/Sequence.hxx"
32 : #include "com/sun/star/uno/XInterface.hpp"
33 : #include "cppu/unotype.hxx"
34 : #include "rtl/byteseq.hxx"
35 : #include "rtl/ref.hxx"
36 : #include "rtl/textcvt.h"
37 : #include "rtl/textenc.h"
38 : #include "rtl/ustring.h"
39 : #include "rtl/ustring.hxx"
40 : #include "sal/types.h"
41 : #include "typelib/typeclass.h"
42 : #include "typelib/typedescription.h"
43 : #include "typelib/typedescription.hxx"
44 : #include "uno/any2.h"
45 : #include "uno/data.h"
46 : #include "uno/dispatcher.hxx"
47 :
48 : #include "binaryany.hxx"
49 : #include "bridge.hxx"
50 : #include "cache.hxx"
51 : #include "readerstate.hxx"
52 : #include "unmarshal.hxx"
53 :
54 : namespace binaryurp {
55 :
56 : namespace {
57 :
58 48801 : void * allocate(sal_Size size) {
59 48801 : void * p = rtl_allocateMemory(size);
60 48801 : if (p == 0) {
61 0 : throw std::bad_alloc();
62 : }
63 48801 : return p;
64 : }
65 :
66 32865 : std::vector< BinaryAny >::iterator copyMemberValues(
67 : css::uno::TypeDescription const & type,
68 : std::vector< BinaryAny >::iterator const & it, void * buffer) throw ()
69 : {
70 : assert(
71 : type.is() &&
72 : (type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
73 : type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
74 : buffer != 0);
75 32865 : type.makeComplete();
76 32865 : std::vector< BinaryAny >::iterator i(it);
77 : typelib_CompoundTypeDescription * ctd =
78 32865 : reinterpret_cast< typelib_CompoundTypeDescription * >(type.get());
79 32865 : if (ctd->pBaseTypeDescription != 0) {
80 : i = copyMemberValues(
81 : css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase), i,
82 230 : buffer);
83 : }
84 142603 : for (sal_Int32 j = 0; j != ctd->nMembers; ++j) {
85 : uno_type_copyData(
86 219476 : static_cast< char * >(buffer) + ctd->pMemberOffsets[j],
87 : const_cast< void * >(
88 219476 : i++->getValue(css::uno::TypeDescription(ctd->ppTypeRefs[j]))),
89 329214 : ctd->ppTypeRefs[j], 0);
90 : }
91 32865 : return i;
92 : }
93 :
94 : }
95 :
96 1048252 : Unmarshal::Unmarshal(
97 : rtl::Reference< Bridge > const & bridge, ReaderState & state,
98 : css::uno::Sequence< sal_Int8 > const & buffer):
99 1048252 : bridge_(bridge), state_(state), buffer_(buffer)
100 : {
101 1048252 : data_ = reinterpret_cast< sal_uInt8 const * >(buffer_.getConstArray());
102 1048252 : end_ = data_ + buffer_.getLength();
103 1048252 : }
104 :
105 1048252 : Unmarshal::~Unmarshal() {}
106 :
107 2546064 : sal_uInt8 Unmarshal::read8() {
108 2546064 : check(1);
109 2546064 : return *data_++;
110 : }
111 :
112 1147220 : sal_uInt16 Unmarshal::read16() {
113 1147220 : check(2);
114 1147220 : sal_uInt16 n = static_cast< sal_uInt16 >(*data_++) << 8;
115 1147220 : return n | *data_++;
116 : }
117 :
118 1163778 : sal_uInt32 Unmarshal::read32() {
119 1163778 : check(4);
120 1163778 : sal_uInt32 n = static_cast< sal_uInt32 >(*data_++) << 24;
121 1163778 : n |= static_cast< sal_uInt32 >(*data_++) << 16;
122 1163778 : n |= static_cast< sal_uInt32 >(*data_++) << 8;
123 1163778 : return n | *data_++;
124 : }
125 :
126 472350 : css::uno::TypeDescription Unmarshal::readType() {
127 472350 : sal_uInt8 flags = read8();
128 472350 : typelib_TypeClass tc = static_cast< typelib_TypeClass >(flags & 0x7F);
129 472350 : switch (tc) {
130 : case typelib_TypeClass_VOID:
131 : case typelib_TypeClass_BOOLEAN:
132 : case typelib_TypeClass_BYTE:
133 : case typelib_TypeClass_SHORT:
134 : case typelib_TypeClass_UNSIGNED_SHORT:
135 : case typelib_TypeClass_LONG:
136 : case typelib_TypeClass_UNSIGNED_LONG:
137 : case typelib_TypeClass_HYPER:
138 : case typelib_TypeClass_UNSIGNED_HYPER:
139 : case typelib_TypeClass_FLOAT:
140 : case typelib_TypeClass_DOUBLE:
141 : case typelib_TypeClass_CHAR:
142 : case typelib_TypeClass_STRING:
143 : case typelib_TypeClass_TYPE:
144 : case typelib_TypeClass_ANY:
145 159075 : if ((flags & 0x80) != 0) {
146 : throw css::io::IOException(
147 0 : "binaryurp::Unmarshal: cache flag of simple type is set");
148 : }
149 : return css::uno::TypeDescription(
150 : *typelib_static_type_getByTypeClass(
151 159075 : static_cast< typelib_TypeClass >(tc)));
152 : case typelib_TypeClass_SEQUENCE:
153 : case typelib_TypeClass_ENUM:
154 : case typelib_TypeClass_STRUCT:
155 : case typelib_TypeClass_EXCEPTION:
156 : case typelib_TypeClass_INTERFACE:
157 : {
158 313275 : sal_uInt16 idx = readCacheIndex();
159 313275 : if ((flags & 0x80) == 0) {
160 309791 : if (idx == cache::ignore || !state_.typeCache[idx].is()) {
161 : throw css::io::IOException(
162 0 : "binaryurp::Unmarshal: unknown type cache index");
163 : }
164 309791 : return state_.typeCache[idx];
165 : } else {
166 3484 : OUString const str(readString());
167 6968 : css::uno::TypeDescription t(str);
168 6968 : if (!t.is() ||
169 3484 : t.get()->eTypeClass != static_cast< typelib_TypeClass >(tc))
170 : {
171 :
172 : throw css::io::IOException(
173 0 : "binaryurp::Unmarshal: type with unknown name: " + str);
174 : }
175 7040 : for (css::uno::TypeDescription t2(t);
176 3556 : t2.get()->eTypeClass == typelib_TypeClass_SEQUENCE;)
177 : {
178 74 : t2.makeComplete();
179 148 : t2 = css::uno::TypeDescription(
180 : reinterpret_cast< typelib_IndirectTypeDescription * >(
181 148 : t2.get())->pType);
182 74 : if (!t2.is()) {
183 : throw css::io::IOException(
184 : "binaryurp::Unmarshal: sequence type with unknown"
185 0 : " component type");
186 : }
187 74 : switch (t2.get()->eTypeClass) {
188 : case typelib_TypeClass_VOID:
189 : case typelib_TypeClass_EXCEPTION:
190 : throw css::io::IOException(
191 : "binaryurp::Unmarshal: sequence type with bad"
192 2 : " component type");
193 : default:
194 72 : break;
195 : }
196 3484 : }
197 3482 : if (idx != cache::ignore) {
198 3480 : state_.typeCache[idx] = t;
199 : }
200 6966 : return t;
201 : }
202 : }
203 : default:
204 : throw css::io::IOException(
205 0 : "binaryurp::Unmarshal: type of unknown type class");
206 : }
207 : }
208 :
209 641277 : OUString Unmarshal::readOid() {
210 641277 : OUString oid(readString());
211 5413466 : for (sal_Int32 i = 0; i != oid.getLength(); ++i) {
212 4772189 : if (oid[i] > 0x7F) {
213 : throw css::io::IOException(
214 0 : "binaryurp::Unmarshal: OID contains non-ASCII character");
215 : }
216 : }
217 641277 : sal_uInt16 idx = readCacheIndex();
218 641277 : if (oid.isEmpty() && idx != cache::ignore) {
219 146481 : if (state_.oidCache[idx].isEmpty()) {
220 : throw css::io::IOException(
221 0 : "binaryurp::Unmarshal: unknown OID cache index");
222 : }
223 146481 : return state_.oidCache[idx];
224 : }
225 494796 : if (idx != cache::ignore) {
226 100780 : state_.oidCache[idx] = oid;
227 : }
228 494796 : return oid;
229 : }
230 :
231 107087 : rtl::ByteSequence Unmarshal::readTid() {
232 : rtl::ByteSequence tid(
233 : *static_cast< sal_Sequence * const * >(
234 : readSequence(
235 : css::uno::TypeDescription(
236 107087 : cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get())).
237 : getValue(
238 : css::uno::TypeDescription(
239 214174 : cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get()))));
240 107087 : sal_uInt16 idx = readCacheIndex();
241 107087 : if (tid.getLength() == 0) {
242 106561 : if (idx == cache::ignore || state_.tidCache[idx].getLength() == 0) {
243 : throw css::io::IOException(
244 0 : "binaryurp::Unmarshal: unknown TID cache index");
245 : }
246 106561 : return state_.tidCache[idx];
247 : }
248 526 : if (idx != cache::ignore) {
249 526 : state_.tidCache[idx] = tid;
250 : }
251 526 : return tid;
252 : }
253 :
254 1377642 : BinaryAny Unmarshal::readValue(css::uno::TypeDescription const & type) {
255 : assert(type.is());
256 1377642 : switch (type.get()->eTypeClass) {
257 : default:
258 0 : std::abort(); // this cannot happen
259 : // pseudo fall-through to avoid compiler warnings
260 : case typelib_TypeClass_VOID:
261 10707 : return BinaryAny();
262 : case typelib_TypeClass_BOOLEAN:
263 : {
264 52538 : sal_uInt8 v = read8();
265 52538 : if (v > 1) {
266 : throw css::io::IOException(
267 0 : "binaryurp::Unmarshal: boolean of unknown value");
268 : }
269 52538 : return BinaryAny(type, &v);
270 : }
271 : case typelib_TypeClass_BYTE:
272 : {
273 46 : sal_uInt8 v = read8();
274 46 : return BinaryAny(type, &v);
275 : }
276 : case typelib_TypeClass_SHORT:
277 : case typelib_TypeClass_UNSIGNED_SHORT:
278 : case typelib_TypeClass_CHAR:
279 : {
280 85581 : sal_uInt16 v = read16();
281 85581 : return BinaryAny(type, &v);
282 : }
283 : case typelib_TypeClass_LONG:
284 : case typelib_TypeClass_UNSIGNED_LONG:
285 : case typelib_TypeClass_FLOAT:
286 : {
287 110632 : sal_uInt32 v = read32();
288 110632 : return BinaryAny(type, &v);
289 : }
290 : case typelib_TypeClass_HYPER:
291 : case typelib_TypeClass_UNSIGNED_HYPER:
292 : case typelib_TypeClass_DOUBLE:
293 : {
294 44596 : sal_uInt64 v = read64();
295 44596 : return BinaryAny(type, &v);
296 : }
297 : case typelib_TypeClass_STRING:
298 : {
299 390127 : OUString v(readString());
300 390127 : return BinaryAny(type, &v.pData);
301 : }
302 : case typelib_TypeClass_TYPE:
303 : {
304 43839 : css::uno::TypeDescription v(readType());
305 43839 : typelib_TypeDescription * p = v.get();
306 43839 : return BinaryAny(type, &p);
307 : }
308 : case typelib_TypeClass_ANY:
309 : {
310 167950 : css::uno::TypeDescription t(readType());
311 167950 : if (t.get()->eTypeClass == typelib_TypeClass_ANY) {
312 : throw css::io::IOException(
313 0 : "binaryurp::Unmarshal: any of type ANY");
314 : }
315 167950 : return readValue(t);
316 : }
317 : case typelib_TypeClass_SEQUENCE:
318 17891 : type.makeComplete();
319 17891 : return readSequence(type);
320 : case typelib_TypeClass_ENUM:
321 : {
322 4862 : sal_Int32 v = static_cast< sal_Int32 >(read32());
323 4862 : type.makeComplete();
324 : typelib_EnumTypeDescription * etd =
325 4862 : reinterpret_cast< typelib_EnumTypeDescription * >(type.get());
326 4862 : bool found = false;
327 14298 : for (sal_Int32 i = 0; i != etd->nEnumValues; ++i) {
328 14298 : if (etd->pEnumValues[i] == v) {
329 4862 : found = true;
330 4862 : break;
331 : }
332 : }
333 4862 : if (!found) {
334 : throw css::io::IOException(
335 0 : "binaryurp::Unmarshal: unknown enum value");
336 : }
337 4862 : return BinaryAny(type, &v);
338 : }
339 : case typelib_TypeClass_STRUCT:
340 : case typelib_TypeClass_EXCEPTION:
341 : {
342 32635 : std::vector< BinaryAny > as;
343 32635 : readMemberValues(type, &as);
344 32635 : void * buf = allocate(type.get()->nSize);
345 32635 : copyMemberValues(type, as.begin(), buf);
346 : uno_Any raw;
347 : raw.pType = reinterpret_cast< typelib_TypeDescriptionReference * >(
348 32635 : type.get());
349 32635 : raw.pData = buf;
350 32635 : raw.pReserved = 0;
351 32635 : return BinaryAny(raw);
352 : }
353 : case typelib_TypeClass_INTERFACE:
354 : {
355 : css::uno::UnoInterfaceReference obj(
356 416238 : bridge_->registerIncomingInterface(readOid(), type));
357 416238 : return BinaryAny(type, &obj.m_pUnoI);
358 : }
359 : }
360 : }
361 :
362 1048250 : void Unmarshal::done() const {
363 1048250 : if (data_ != end_) {
364 : throw css::io::IOException(
365 0 : "binaryurp::Unmarshal: block contains excess data");
366 : }
367 1048250 : }
368 :
369 5937108 : void Unmarshal::check(sal_Int32 size) const {
370 5937108 : if (end_ - data_ < size) {
371 : throw css::io::IOException(
372 0 : "binaryurp::Unmarshal: trying to read past end of block");
373 : }
374 5937108 : }
375 :
376 1159866 : sal_uInt32 Unmarshal::readCompressed() {
377 1159866 : sal_uInt8 n = read8();
378 1159866 : return n == 0xFF ? read32() : n;
379 : }
380 :
381 1061639 : sal_uInt16 Unmarshal::readCacheIndex() {
382 1061639 : sal_uInt16 idx = read16();
383 1061639 : if (idx >= cache::size && idx != cache::ignore) {
384 : throw css::io::IOException(
385 0 : "binaryurp::Unmarshal: cache index out of range");
386 : }
387 1061639 : return idx;
388 : }
389 :
390 44596 : sal_uInt64 Unmarshal::read64() {
391 44596 : check(8);
392 44596 : sal_uInt64 n = static_cast< sal_uInt64 >(*data_++) << 56;
393 44596 : n |= static_cast< sal_uInt64 >(*data_++) << 48;
394 44596 : n |= static_cast< sal_uInt64 >(*data_++) << 40;
395 44596 : n |= static_cast< sal_uInt64 >(*data_++) << 32;
396 44596 : n |= static_cast< sal_uInt64 >(*data_++) << 24;
397 44596 : n |= static_cast< sal_uInt64 >(*data_++) << 16;
398 44596 : n |= static_cast< sal_uInt64 >(*data_++) << 8;
399 44596 : return n | *data_++;
400 : }
401 :
402 1034888 : OUString Unmarshal::readString() {
403 1034888 : sal_uInt32 n = readCompressed();
404 1034888 : if (n > SAL_MAX_INT32) {
405 : throw css::uno::RuntimeException(
406 0 : "binaryurp::Unmarshal: string size too large");
407 : }
408 1034888 : check(static_cast< sal_Int32 >(n));
409 1034888 : OUString s;
410 1034888 : if (!rtl_convertStringToUString(
411 : &s.pData, reinterpret_cast< char const * >(data_),
412 : static_cast< sal_Int32 >(n), RTL_TEXTENCODING_UTF8,
413 : (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
414 : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
415 1034888 : RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
416 : {
417 : throw css::io::IOException(
418 0 : "binaryurp::Unmarshal: string does not contain UTF-8");
419 : }
420 1034888 : data_ += n;
421 1034888 : return s;
422 : }
423 :
424 124978 : BinaryAny Unmarshal::readSequence(css::uno::TypeDescription const & type) {
425 : assert(type.is() && type.get()->eTypeClass == typelib_TypeClass_SEQUENCE);
426 124978 : sal_uInt32 n = readCompressed();
427 124978 : if (n > SAL_MAX_INT32) {
428 : throw css::uno::RuntimeException(
429 0 : "binaryurp::Unmarshal: sequence size too large");
430 : }
431 124978 : if (n == 0) {
432 108250 : return BinaryAny(type, 0);
433 : }
434 : css::uno::TypeDescription ctd(
435 : reinterpret_cast< typelib_IndirectTypeDescription * >(
436 16728 : type.get())->pType);
437 16728 : if (ctd.get()->eTypeClass == typelib_TypeClass_BYTE) {
438 562 : check(static_cast< sal_Int32 >(n));
439 : rtl::ByteSequence s(
440 : reinterpret_cast< sal_Int8 const * >(data_),
441 562 : static_cast< sal_Int32 >(n));
442 562 : data_ += n;
443 562 : sal_Sequence * p = s.getHandle();
444 562 : return BinaryAny(type, &p);
445 : }
446 32332 : std::vector< BinaryAny > as;
447 390036 : for (sal_uInt32 i = 0; i != n; ++i) {
448 373870 : as.push_back(readValue(ctd));
449 : }
450 : assert(ctd.get()->nSize >= 0);
451 32332 : sal_uInt64 size = static_cast< sal_uInt64 >(n) *
452 32332 : static_cast< sal_uInt64 >(ctd.get()->nSize);
453 : // sal_uInt32 * sal_Int32 -> sal_uInt64 cannot overflow
454 16166 : if (size > SAL_MAX_SIZE - SAL_SEQUENCE_HEADER_SIZE) {
455 : throw css::uno::RuntimeException(
456 0 : "binaryurp::Unmarshal: sequence size too large");
457 : }
458 : void * buf = allocate(
459 16166 : SAL_SEQUENCE_HEADER_SIZE + static_cast< sal_Size >(size));
460 16166 : static_cast< sal_Sequence * >(buf)->nRefCount = 0;
461 : static_cast< sal_Sequence * >(buf)->nElements =
462 16166 : static_cast< sal_Int32 >(n);
463 390036 : for (sal_uInt32 i = 0; i != n; ++i) {
464 : uno_copyData(
465 373870 : static_cast< sal_Sequence * >(buf)->elements + i * ctd.get()->nSize,
466 747740 : const_cast< void * >(as[i].getValue(ctd)), ctd.get(), 0);
467 : }
468 32894 : return BinaryAny(type, reinterpret_cast< sal_Sequence ** >(&buf));
469 : }
470 :
471 32865 : void Unmarshal::readMemberValues(
472 : css::uno::TypeDescription const & type, std::vector< BinaryAny > * values)
473 : {
474 : assert(
475 : type.is() &&
476 : (type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
477 : type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
478 : values != 0);
479 32865 : type.makeComplete();
480 : typelib_CompoundTypeDescription * ctd =
481 32865 : reinterpret_cast< typelib_CompoundTypeDescription * >(type.get());
482 32865 : if (ctd->pBaseTypeDescription != 0) {
483 : readMemberValues(
484 : css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase),
485 230 : values);
486 : }
487 142603 : for (sal_Int32 i = 0; i != ctd->nMembers; ++i) {
488 : values->push_back(
489 109738 : readValue(css::uno::TypeDescription(ctd->ppTypeRefs[i])));
490 : }
491 32865 : }
492 :
493 : }
494 :
495 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|