summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-06-08 06:42:50 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-06-08 06:42:50 +0000
commit670140e7cf1547b5337ee0065cbb375e9416c5c6 (patch)
tree6549d5f998871ebfa8a3bf1b600ce44b37b0e9fb
parente3947edd23a33c294d6a41a50af8ac098aa82da9 (diff)
merge revision(s) 27459:
* ext/win32ole/win32ole.c (ole_val2variant): fix the core dump when converting Array object to VT_ARRAY variant. [ruby-core:28446] [Bug #2836] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@28213 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--ext/win32ole/win32ole.c217
-rw-r--r--version.h2
3 files changed, 157 insertions, 68 deletions
diff --git a/ChangeLog b/ChangeLog
index 8789818793..919dfbde5d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Tue Jun 8 15:43:43 2010 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_val2variant): fix the core dump
+ when converting Array object to VT_ARRAY variant. [ruby-core:28446]
+ [Bug #2836]
+
Tue Jun 8 15:34:15 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
* file.c (rb_file_s_extname): skip last directory separators.
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index ae0066ffc9..8d37c3559b 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -12,7 +12,6 @@
*/
/*
- $Date$
modified for win32ole (ruby) by Masaki.Suketa <masaki.suketa@nifty.ne.jp>
*/
@@ -79,7 +78,7 @@
#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
-#define WIN32OLE_VERSION "0.7.6"
+#define WIN32OLE_VERSION "0.7.8"
typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
(REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
@@ -822,6 +821,71 @@ ole_ary_m_entry(val, pid)
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;
@@ -832,22 +896,96 @@ ole_set_safe_array(n, psa, pid, pub, val, dim)
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;
+ }
+ }
+}
+
+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");
}
- pid[n] += 1;
- if (pid[n] < pub[n]) {
- ole_set_safe_array(dim, psa, pid, pub, val, dim);
+
+ 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
@@ -870,63 +1008,8 @@ ole_val2variant(val, var)
}
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);
diff --git a/version.h b/version.h
index 175774c67c..8461c895a4 100644
--- a/version.h
+++ b/version.h
@@ -2,7 +2,7 @@
#define RUBY_RELEASE_DATE "2010-06-08"
#define RUBY_VERSION_CODE 187
#define RUBY_RELEASE_CODE 20100608
-#define RUBY_PATCHLEVEL 277
+#define RUBY_PATCHLEVEL 278
#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8