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