ruby-changes:15555
From: suke <ko1@a...>
Date: Fri, 23 Apr 2010 18:58:43 +0900 (JST)
Subject: [ruby-changes:15555] Ruby:r27459 (ruby_1_8): * ext/win32ole/win32ole.c (ole_val2variant): fix the core dump
suke 2010-04-23 18:58:31 +0900 (Fri, 23 Apr 2010) New Revision: 27459 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=27459 Log: * ext/win32ole/win32ole.c (ole_val2variant): fix the core dump when converting Array object to VT_ARRAY variant. [ruby-core:28446] [Bug #2836] Modified files: branches/ruby_1_8/ChangeLog branches/ruby_1_8/ext/win32ole/win32ole.c Index: ruby_1_8/ext/win32ole/win32ole.c =================================================================== --- ruby_1_8/ext/win32ole/win32ole.c (revision 27458) +++ ruby_1_8/ext/win32ole/win32ole.c (revision 27459) @@ -12,7 +12,6 @@ */ /* - $Date$ modified for win32ole (ruby) by Masaki.Suketa <masaki.suketa@n...> */ @@ -80,7 +79,7 @@ #define WC2VSTR(x) ole_wc2vstr((x), TRUE) -#define WIN32OLE_VERSION "0.7.7" +#define WIN32OLE_VERSION "0.7.8" typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); @@ -823,6 +822,71 @@ return obj; } +static VALUE +is_all_index_under(pid, pub, dim) + long *pid; + long *pub; + long dim; +{ + long i = 0; + for (i = 0; i < dim; i++) { + if (pid[i] > pub[i]) { + return Qfalse; + } + } + return Qtrue; +} + +static long +dimension(val) + VALUE val; +{ + long dim = 0; + long dim1 = 0; + long len = 0; + long i = 0; + if (TYPE(val) == T_ARRAY) { + len = RARRAY(val)->len; + for (i = 0; i < len; i++) { + dim1 = dimension(rb_ary_entry(val, i)); + if (dim < dim1) { + dim = dim1; + } + } + dim += 1; + } + return dim; +} + +static long +ary_len_of_dim(ary, dim) + VALUE ary; + long dim; +{ + long ary_len = 0; + long ary_len1 = 0; + long len = 0; + long i = 0; + VALUE val; + if (dim == 0) { + if (TYPE(ary) == T_ARRAY) { + ary_len = RARRAY(ary)->len; + } + } else { + if (TYPE(ary) == T_ARRAY) { + len = RARRAY(ary)->len; + for (i = 0; i < len; i++) { + val = rb_ary_entry(ary, i); + ary_len1 = ary_len_of_dim(val, dim-1); + if (ary_len < ary_len1) { + ary_len = ary_len1; + } + } + } + } + return ary_len; +} + static void ole_set_safe_array(n, psa, pid, pub, val, dim) long n; @@ -833,22 +897,96 @@ long dim; { VALUE val1; + HRESULT hr = S_OK; VARIANT var; - VariantInit(&var); - if(n < 0) return; - if(n == dim) { + VOID *p = NULL; + long i = n; + while(i >= 0) { val1 = ole_ary_m_entry(val, pid); + VariantInit(&var); ole_val2variant(val1, &var); - SafeArrayPutElement(psa, pid, &var); + if (is_all_index_under(pid, pub, dim) == Qtrue) { + if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) || + (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) { + rb_raise(eWIN32OLE_RUNTIME_ERROR, "element of array does not have IDispatch or IUnknown Interface"); + } + hr = SafeArrayPutElement(psa, pid, &var); + } + if (FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayPutElement"); + } + pid[i] += 1; + if (pid[i] > pub[i]) { + pid[i] = 0; + i -= 1; + } else { + i = dim - 1; + } } - pid[n] += 1; - if (pid[n] < pub[n]) { - ole_set_safe_array(dim, psa, pid, pub, val, dim); +} + +static HRESULT +ole_val_ary2variant_ary(val, var, vt) + VALUE val; + VARIANT *var; + VARTYPE vt; +{ + long dim = 0; + int i = 0; + HRESULT hr = S_OK; + + SAFEARRAYBOUND *psab = NULL; + SAFEARRAY *psa = NULL; + long *pub, *pid; + + Check_Type(val, T_ARRAY); + + dim = dimension(val); + + psab = ALLOC_N(SAFEARRAYBOUND, dim); + pub = ALLOC_N(long, dim); + pid = ALLOC_N(long, dim); + + if(!psab || !pub || !pid) { + if(pub) free(pub); + if(psab) free(psab); + if(pid) free(pid); + rb_raise(rb_eRuntimeError, "memory allocation error"); } + + for (i = 0; i < dim; i++) { + psab[i].cElements = ary_len_of_dim(val, i); + psab[i].lLbound = 0; + pub[i] = psab[i].cElements - 1; + pid[i] = 0; + } + /* Create and fill VARIANT array */ + if ((vt & ~VT_BYREF) == VT_ARRAY) { + vt = (vt | VT_VARIANT); + } + psa = SafeArrayCreate(VT_VARIANT, dim, psab); + if (psa == NULL) + hr = E_OUTOFMEMORY; + else + hr = SafeArrayLock(psa); + if (SUCCEEDED(hr)) { + ole_set_safe_array(dim-1, psa, pid, pub, val, dim); + hr = SafeArrayUnlock(psa); + } + + if(pub) free(pub); + if(psab) free(psab); + if(pid) free(pid); + + if (SUCCEEDED(hr)) { + V_VT(var) = vt; + V_ARRAY(var) = psa; + } else { - pid[n] = 0; - ole_set_safe_array(n-1, psa, pid, pub, val, dim); + if (psa != NULL) + SafeArrayDestroy(psa); } + return hr; } static void @@ -871,63 +1009,8 @@ } switch (TYPE(val)) { case T_ARRAY: - { - VALUE val1; - long dim = 0; - int i = 0; - - HRESULT hr; - SAFEARRAYBOUND *psab; - SAFEARRAY *psa; - long *pub, *pid; - - val1 = val; - while(TYPE(val1) == T_ARRAY) { - val1 = rb_ary_entry(val1, 0); - dim += 1; - } - psab = ALLOC_N(SAFEARRAYBOUND, dim); - pub = ALLOC_N(long, dim); - pid = ALLOC_N(long, dim); - - if(!psab || !pub || !pid) { - if(pub) free(pub); - if(psab) free(psab); - if(pid) free(pid); - rb_raise(rb_eRuntimeError, "memory allocation error"); - } - val1 = val; - i = 0; - while(TYPE(val1) == T_ARRAY) { - psab[i].cElements = RARRAY(val1)->len; - psab[i].lLbound = 0; - pub[i] = psab[i].cElements; - pid[i] = 0; - i ++; - val1 = rb_ary_entry(val1, 0); - } - /* Create and fill VARIANT array */ - psa = SafeArrayCreate(VT_VARIANT, dim, psab); - if (psa == NULL) - hr = E_OUTOFMEMORY; - else - hr = SafeArrayLock(psa); - if (SUCCEEDED(hr)) { - ole_set_safe_array(dim-1, psa, pid, pub, val, dim-1); - hr = SafeArrayUnlock(psa); - } - if(pub) free(pub); - if(psab) free(psab); - if(pid) free(pid); - - if (SUCCEEDED(hr)) { - V_VT(var) = VT_VARIANT | VT_ARRAY; - V_ARRAY(var) = psa; - } - else if (psa != NULL) - SafeArrayDestroy(psa); + ole_val_ary2variant_ary(val, var, VT_VARIANT|VT_ARRAY); break; - } case T_STRING: V_VT(var) = VT_BSTR; V_BSTR(var) = ole_mb2wc(StringValuePtr(val), -1); Index: ruby_1_8/ChangeLog =================================================================== --- ruby_1_8/ChangeLog (revision 27458) +++ ruby_1_8/ChangeLog (revision 27459) @@ -1,3 +1,9 @@ +Fri Apr 23 18:52:13 2010 Masaki Suketa <masaki.suketa@n...> + + * ext/win32ole/win32ole.c (ole_val2variant): fix the core dump + when converting Array object to VT_ARRAY variant. [ruby-core:28446] + [Bug #2836] + Fri Apr 23 14:07:36 2010 Nobuyoshi Nakada <nobu@r...> * doc/etc.rd, doc/etc.rd.ja: moved from ext/etc. -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/