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 "precompiled_bridges.hxx"
25 #include "sal/config.h"
26 
27 #include <cstddef>
28 #include <cstring>
29 #include <map>
30 #include <utility>
31 #include <vector>
32 
33 #include "bridges/cpp_uno/shared/arraypointer.hxx"
34 #include "com/sun/star/uno/Reference.hxx"
35 #include "com/sun/star/uno/RuntimeException.hpp"
36 #include "com/sun/star/uno/XInterface.hpp"
37 #include "com/sun/star/uno/genfunc.hxx"
38 #include "osl/diagnose.h"
39 #include "osl/mutex.hxx"
40 #include "rtl/strbuf.hxx"
41 #include "rtl/string.hxx"
42 #include "rtl/textenc.h"
43 #include "rtl/ustring.h"
44 #include "rtl/ustring.hxx"
45 #include "sal/types.h"
46 #include "typelib/typeclass.h"
47 #include "typelib/typedescription.h"
48 #include "uno/any2.h"
49 #include "uno/data.h"
50 #include "uno/mapping.h"
51 
52 #include "exceptions.hxx"
53 #include "flushcode.hxx"
54 
55 namespace {
56 
57 namespace css = com::sun::star;
58 
59 typedef void (* Function)(void *);
60 
toFunction(void * pointer)61 Function toFunction(void * pointer) {
62 #pragma disable_warn
63     return reinterpret_cast< Function >(pointer);
64 #pragma enable_warn
65 }
66 
toUnoName(char const * rttiName,rtl::OUString * unoName)67 bool toUnoName(char const * rttiName, rtl::OUString * unoName) {
68     rtl::OStringBuffer buf;
69     for (;;) {
70         char const * p = std::strchr(rttiName, ':');
71         if (p == NULL) {
72             buf.append(rttiName);
73             break;
74         }
75         if (p - rttiName > SAL_MAX_INT32) {
76             return false;
77         }
78         buf.append(rttiName, sal::static_int_cast< sal_Int32 >(p - rttiName));
79         buf.append(".");
80         while (*p == ':') {
81             ++p;
82         }
83         rttiName = p;
84     }
85     *unoName = rtl::OStringToOUString(
86         buf.makeStringAndClear(), RTL_TEXTENCODING_UTF8);
87         //TODO: check conversion failure
88     return true;
89 }
90 
91 class NistHash {
92 public:
93     NistHash(rtl::OString const & text);
94 
95     sal_uInt32 hashdata[5];
96 
97 private:
f1(sal_uInt32 x,sal_uInt32 y,sal_uInt32 z)98     static sal_uInt32 f1(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z)
99     { return z ^ (x & (y ^ z)); }
100 
f2(sal_uInt32 x,sal_uInt32 y,sal_uInt32 z)101     static sal_uInt32 f2(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z)
102     { return x ^ y ^ z; }
103 
f3(sal_uInt32 x,sal_uInt32 y,sal_uInt32 z)104     static sal_uInt32 f3(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z)
105     { return (x & y) + (z & (x ^ y)); }
106 
rotl(sal_uInt32 value,sal_uInt32 bits)107     static sal_uInt32 rotl(sal_uInt32 value, sal_uInt32 bits)
108     { return (value << bits) | (value >> (32 - bits)); }
109 
expand_nostore(sal_uInt32 index)110     sal_uInt32 expand_nostore(sal_uInt32 index) {
111         return data[index & 15] ^ data[(index - 14) & 15] ^
112             data[(index - 8) & 15] ^ data[(index - 3) & 15];
113     }
114 
expand_store(sal_uInt32 index)115     sal_uInt32 expand_store(sal_uInt32 index) {
116         return data[index & 15] ^= data[(index - 14) & 15] ^
117             data[(index - 8) & 15] ^ data[(index - 3) & 15];
118     }
119 
subRound(sal_uInt32 a,sal_uInt32 & b,sal_uInt32 c,sal_uInt32 d,sal_uInt32 & e,sal_uInt32 constant,sal_uInt32 datum,sal_uInt32 function)120     void subRound(
121         sal_uInt32 a, sal_uInt32 & b, sal_uInt32 c, sal_uInt32 d,
122         sal_uInt32 & e, sal_uInt32 constant, sal_uInt32 datum,
123         sal_uInt32 function)
124     {
125         e += rotl(a, 5);
126         switch (function) {
127             case 1:
128                 e += f1(b, c, d);
129                 break;
130             case 2:
131             case 4:
132                 e += f2(b, c, d);
133                 break;
134             case 3:
135                 e += f3(b, c, d);
136                 break;
137         }
138         e += constant + datum;
139         b = rotl(b, 30);
140     }
141 
142     void transform();
143 
144     sal_uInt32 data[16];
145 };
146 
NistHash(rtl::OString const & text)147 NistHash::NistHash(rtl::OString const & text) {
148     hashdata[0] = 0x67452301;
149     hashdata[1] = 0xefcdab89;
150     hashdata[2] = 0x98badcfe;
151     hashdata[3] = 0x10325476;
152     hashdata[4] = 0xc3d2e1f0;
153     char const * p = text.getStr();
154     sal_Int32 n = text.getLength();
155     while (n >= sizeof data) {
156         std::memcpy(data, p, sizeof data);
157         p += sizeof data;
158         n -= sizeof data;
159         transform();
160     }
161     std::memcpy(data, p, n);
162     reinterpret_cast< unsigned char *>(data)[n++] = 0x80;
163     if (n > sizeof data - 8) {
164         std::memset(reinterpret_cast< char * >(data) + n, 0, sizeof data - n);
165         transform();
166         std::memset(data, 0, sizeof data  - 8);
167     } else {
168         std::memset(
169             reinterpret_cast< char * >(data) + n, 0, sizeof data - 8 - n);
170     }
171     data[14] = 0;
172     data[15] = text.getLength() << 3;
173     transform();
174 }
175 
transform()176 void NistHash::transform() {
177     sal_uInt32 const K2 = 0x5A827999;
178     sal_uInt32 const K3 = 0x6ED9EBA1;
179     sal_uInt32 const K5 = 0x8F1BBCDC;
180     sal_uInt32 const K10 = 0xCA62C1D6;
181     sal_uInt32 a = hashdata[0];
182     sal_uInt32 b = hashdata[1];
183     sal_uInt32 c = hashdata[2];
184     sal_uInt32 d = hashdata[3];
185     sal_uInt32 e = hashdata[4];
186     subRound(a, b, c, d, e, K2, data[ 0], 1);
187     subRound(e, a, b, c, d, K2, data[ 1], 1);
188     subRound(d, e, a, b, c, K2, data[ 2], 1);
189     subRound(c, d, e, a, b, K2, data[ 3], 1);
190     subRound(b, c, d, e, a, K2, data[ 4], 1);
191     subRound(a, b, c, d, e, K2, data[ 5], 1);
192     subRound(e, a, b, c, d, K2, data[ 6], 1);
193     subRound(d, e, a, b, c, K2, data[ 7], 1);
194     subRound(c, d, e, a, b, K2, data[ 8], 1);
195     subRound(b, c, d, e, a, K2, data[ 9], 1);
196     subRound(a, b, c, d, e, K2, data[10], 1);
197     subRound(e, a, b, c, d, K2, data[11], 1);
198     subRound(d, e, a, b, c, K2, data[12], 1);
199     subRound(c, d, e, a, b, K2, data[13], 1);
200     subRound(b, c, d, e, a, K2, data[14], 1);
201     subRound(a, b, c, d, e, K2, data[15], 1);
202     subRound(e, a, b, c, d, K2, expand_store(16), 1);
203     subRound(d, e, a, b, c, K2, expand_store(17), 1);
204     subRound(c, d, e, a, b, K2, expand_store(18), 1);
205     subRound(b, c, d, e, a, K2, expand_store(19), 1);
206     subRound(a, b, c, d, e, K3, expand_store(20), 2);
207     subRound(e, a, b, c, d, K3, expand_store(21), 2);
208     subRound(d, e, a, b, c, K3, expand_store(22), 2);
209     subRound(c, d, e, a, b, K3, expand_store(23), 2);
210     subRound(b, c, d, e, a, K3, expand_store(24), 2);
211     subRound(a, b, c, d, e, K3, expand_store(25), 2);
212     subRound(e, a, b, c, d, K3, expand_store(26), 2);
213     subRound(d, e, a, b, c, K3, expand_store(27), 2);
214     subRound(c, d, e, a, b, K3, expand_store(28), 2);
215     subRound(b, c, d, e, a, K3, expand_store(29), 2);
216     subRound(a, b, c, d, e, K3, expand_store(30), 2);
217     subRound(e, a, b, c, d, K3, expand_store(31), 2);
218     subRound(d, e, a, b, c, K3, expand_store(32), 2);
219     subRound(c, d, e, a, b, K3, expand_store(33), 2);
220     subRound(b, c, d, e, a, K3, expand_store(34), 2);
221     subRound(a, b, c, d, e, K3, expand_store(35), 2);
222     subRound(e, a, b, c, d, K3, expand_store(36), 2);
223     subRound(d, e, a, b, c, K3, expand_store(37), 2);
224     subRound(c, d, e, a, b, K3, expand_store(38), 2);
225     subRound(b, c, d, e, a, K3, expand_store(39), 2);
226     subRound(a, b, c, d, e, K5, expand_store(40), 3);
227     subRound(e, a, b, c, d, K5, expand_store(41), 3);
228     subRound(d, e, a, b, c, K5, expand_store(42), 3);
229     subRound(c, d, e, a, b, K5, expand_store(43), 3);
230     subRound(b, c, d, e, a, K5, expand_store(44), 3);
231     subRound(a, b, c, d, e, K5, expand_store(45), 3);
232     subRound(e, a, b, c, d, K5, expand_store(46), 3);
233     subRound(d, e, a, b, c, K5, expand_store(47), 3);
234     subRound(c, d, e, a, b, K5, expand_store(48), 3);
235     subRound(b, c, d, e, a, K5, expand_store(49), 3);
236     subRound(a, b, c, d, e, K5, expand_store(50), 3);
237     subRound(e, a, b, c, d, K5, expand_store(51), 3);
238     subRound(d, e, a, b, c, K5, expand_store(52), 3);
239     subRound(c, d, e, a, b, K5, expand_store(53), 3);
240     subRound(b, c, d, e, a, K5, expand_store(54), 3);
241     subRound(a, b, c, d, e, K5, expand_store(55), 3);
242     subRound(e, a, b, c, d, K5, expand_store(56), 3);
243     subRound(d, e, a, b, c, K5, expand_store(57), 3);
244     subRound(c, d, e, a, b, K5, expand_store(58), 3);
245     subRound(b, c, d, e, a, K5, expand_store(59), 3);
246     subRound(a, b, c, d, e, K10, expand_store(60), 4);
247     subRound(e, a, b, c, d, K10, expand_store(61), 4);
248     subRound(d, e, a, b, c, K10, expand_store(62), 4);
249     subRound(c, d, e, a, b, K10, expand_store(63), 4);
250     subRound(b, c, d, e, a, K10, expand_store(64), 4);
251     subRound(a, b, c, d, e, K10, expand_store(65), 4);
252     subRound(e, a, b, c, d, K10, expand_store(66), 4);
253     subRound(d, e, a, b, c, K10, expand_store(67), 4);
254     subRound(c, d, e, a, b, K10, expand_store(68), 4);
255     subRound(b, c, d, e, a, K10, expand_store(69), 4);
256     subRound(a, b, c, d, e, K10, expand_store(70), 4);
257     subRound(e, a, b, c, d, K10, expand_store(71), 4);
258     subRound(d, e, a, b, c, K10, expand_store(72), 4);
259     subRound(c, d, e, a, b, K10, expand_store(73), 4);
260     subRound(b, c, d, e, a, K10, expand_store(74), 4);
261     subRound(a, b, c, d, e, K10, expand_store(75), 4);
262     subRound(e, a, b, c, d, K10, expand_store(76), 4);
263     subRound(d, e, a, b, c, K10, expand_nostore(77), 4);
264     subRound(c, d, e, a, b, K10, expand_nostore(78), 4);
265     subRound(b, c, d, e, a, K10, expand_nostore(79), 4);
266     hashdata[0] += a;
267     hashdata[1] += b;
268     hashdata[2] += c;
269     hashdata[3] += d;
270     hashdata[4] += e;
271 }
272 
273 class RttiMap {
274 public:
275     static __Crun::static_type_info const * get(
276         typelib_CompoundTypeDescription const * type);
277 
278 private:
279     RttiMap(); // not defined
280     RttiMap(RttiMap &); // not defined
281     ~RttiMap(); // not defined
282     void operator =(RttiMap &); // not defined
283 
284     struct Data {
285         __Crun::static_type_info * info;
286         rtl::OString cppName;
287         std::vector< __Crun::class_base_descr > bases;
288     };
289     typedef std::map< rtl::OUString, Data > Map;
290 
291     static void toCppNames(
292         rtl::OUString const & unoName, rtl::OString * cppName,
293         rtl::OString * rttiName);
294 
295     static Data const & get_(typelib_CompoundTypeDescription const * type);
296 
297     static osl::Mutex m_mutex;
298     static Map * m_map;
299 };
300 
301 osl::Mutex RttiMap::m_mutex;
302 RttiMap::Map * RttiMap::m_map;
303 
get(typelib_CompoundTypeDescription const * type)304 __Crun::static_type_info const * RttiMap::get(
305     typelib_CompoundTypeDescription const * type)
306 {
307     osl::MutexGuard g(m_mutex);
308     if (m_map == NULL) {
309         m_map = new Map; // leaked
310     }
311     return get_(type).info;
312 }
313 
toCppNames(rtl::OUString const & unoName,rtl::OString * cppName,rtl::OString * rttiName)314 void RttiMap::toCppNames(
315     rtl::OUString const & unoName, rtl::OString * cppName,
316     rtl::OString * rttiName)
317 {
318     OSL_ASSERT(cppName != NULL && rttiName != NULL);
319     rtl::OStringBuffer bc;
320     rtl::OStringBuffer br;
321     br.append("__1n");
322     for (sal_Int32 i = 0; i != -1;) {
323         rtl::OUString tok(unoName.getToken(0, '.', i));
324         bc.append(rtl::OUStringToOString(tok, RTL_TEXTENCODING_UTF8));
325             // conversion should never fail, as tok should be well-formed ASCII
326         if (i != -1) {
327             bc.append("::");
328         }
329         sal_Int32 len = tok.getLength();
330         sal_Int32 pos = br.getLength();
331         for (sal_Int32 n = len / 26; n > 0; n /= 26) {
332             br.insert(pos, static_cast< char >('a' + (n % 26)));
333         }
334         br.append(static_cast< char >('A' + (len % 26)));
335         for (sal_Int32 j = 0; j < len; ++j) {
336             sal_Unicode c = tok[j];
337             OSL_ASSERT(
338                 c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' ||
339                 c >= 'a' && c <= 'z');
340             if (c == 'Q') {
341                 br.append("QdD");
342             } else {
343                 br.append(static_cast< char >(c));
344             }
345         }
346     }
347     br.append('_');
348     *cppName = bc.makeStringAndClear();
349     *rttiName = br.makeStringAndClear();
350 }
351 
get_(typelib_CompoundTypeDescription const * type)352 RttiMap::Data const & RttiMap::get_(
353     typelib_CompoundTypeDescription const * type)
354 {
355     rtl::OUString name(type->aBase.pTypeName);
356     Map::iterator it(m_map->find(name));
357     if (it == m_map->end()) {
358         it = m_map->insert(std::make_pair(name, Data())).first;
359         Data & data = it->second;
360         rtl::OString rttiName;
361         toCppNames(name, &data.cppName, &rttiName);
362         data.info = new __Crun::static_type_info;
363         data.info->ty_name = data.cppName.getStr() -
364             reinterpret_cast< char * >(&data.info->ty_name);
365         data.info->reserved = 0;
366         NistHash hash(rttiName);
367         data.info->type_hash[0] = hash.hashdata[0];
368         data.info->type_hash[1] = hash.hashdata[1];
369         data.info->type_hash[2] = hash.hashdata[2];
370         data.info->type_hash[3] = hash.hashdata[3];
371         data.info->flags = 0;
372         data.info->cv_qualifiers = 0;
373         if (type->pBaseTypeDescription != NULL) {
374             data.bases = get_(type->pBaseTypeDescription).bases;
375             OSL_ASSERT(!data.bases.empty());
376             data.bases.back().offset = 0;
377         }
378         __Crun::class_base_descr last;
379         last.type_hash[0] = data.info->type_hash[0];
380         last.type_hash[1] = data.info->type_hash[1];
381         last.type_hash[2] = data.info->type_hash[2];
382         last.type_hash[3] = data.info->type_hash[3];
383         last.offset = 0x8000000000000000;
384         data.bases.push_back(last);
385         data.info->base_table = reinterpret_cast< char * >(&data.bases[0]) -
386             reinterpret_cast< char * >(&data.info->base_table);
387     }
388     return it->second;
389 }
390 
deleteException(void * exception,unsigned int * thunk,typelib_TypeDescription * type)391 void deleteException(
392     void * exception, unsigned int * thunk, typelib_TypeDescription * type)
393 {
394     uno_destructData(
395         exception, type,
396         reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release));
397     typelib_typedescription_release(type);
398     delete[] thunk;
399 }
400 
401 }
402 
403 namespace bridges { namespace cpp_uno { namespace cc5_solaris_sparc64 {
404 
raiseException(uno_Any * exception,uno_Mapping * unoToCpp)405 void raiseException(uno_Any * exception, uno_Mapping * unoToCpp) {
406     bridges::cpp_uno::shared::ArrayPointer< unsigned long > thunkPtr(
407         new unsigned long[4]);
408     typelib_TypeDescription * type = NULL;
409     typelib_typedescriptionreference_getDescription(&type, exception->pType);
410     __Crun::static_type_info const * rtti = RttiMap::get(
411         reinterpret_cast< typelib_CompoundTypeDescription * >(type));
412     void * exc = __Crun::ex_alloc(type->nSize);
413     uno_copyAndConvertData(exc, exception->pData, type, unoToCpp);
414     uno_any_destruct(exception, NULL);
415     unsigned long * thunk = thunkPtr.release();
416     // 0*4: rd %pc, %o1:
417     // 1*4: ldx %o1, (6-0)*4, %o3:
418     thunk[0] = 0x93414000D65A6018;
419     // 2*4: jmpl %o3, %g0, %g0:
420     // 3*4: ldx %o1, (4-0)*4, %o2:
421     thunk[1] = 0x81C2C000D45A6010;
422     // 4*4: .xword type:
423     thunk[2] = reinterpret_cast< unsigned long >(type);
424     // 6*4: .xword deleteException:
425     thunk[3] = reinterpret_cast< unsigned long >(deleteException);
426     flushCode(thunk, thunk + 4);
427     __Crun::ex_throw(exc, rtti, toFunction(thunk));
428 }
429 
fillUnoException(void * cppException,char const * cppName,uno_Any * unoException,uno_Mapping * cppToUno)430 void fillUnoException(
431     void * cppException, char const * cppName, uno_Any * unoException,
432     uno_Mapping * cppToUno)
433 {
434     rtl::OUString name;
435     typelib_TypeDescription * type = NULL;
436     if (toUnoName(cppName, &name)) {
437         typelib_typedescription_getByName(&type, name.pData);
438     }
439     if (type == NULL || type->eTypeClass != typelib_TypeClass_EXCEPTION) {
440         css::uno::RuntimeException exc(
441             (rtl::OUString(
442                 RTL_CONSTASCII_USTRINGPARAM("Not a UNO exception type: ")) +
443              name),
444             css::uno::Reference< css::uno::XInterface >());
445         uno_type_any_constructAndConvert(
446             unoException, &exc, getCppuType(&exc).getTypeLibType(), cppToUno);
447     } else {
448         uno_any_constructAndConvert(unoException, cppException, type, cppToUno);
449     }
450     if (type != NULL) {
451         typelib_typedescription_release(type);
452     }
453 }
454 
455 } } }
456