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