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 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 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 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 111 Unmarshal::~Unmarshal() {} 112 113 sal_uInt8 Unmarshal::read8() { 114 check(1); 115 return *data_++; 116 } 117 118 sal_uInt16 Unmarshal::read16() { 119 check(2); 120 sal_uInt16 n = static_cast< sal_uInt16 >(*data_++) << 8; 121 return n | *data_++; 122 } 123 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 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 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.getLength() == 0 && idx != cache::ignore) { 248 if (state_.oidCache[idx].getLength() == 0) { 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 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 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 406 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 416 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 426 sal_uInt32 Unmarshal::readCompressed() { 427 sal_uInt8 n = read8(); 428 return n == 0xFF ? read32() : n; 429 } 430 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 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 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 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 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