ruby-oci8 2.2.4.1 → 2.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/ChangeLog +311 -1
  3. data/NEWS +278 -46
  4. data/README.md +5 -2
  5. data/dist-files +8 -4
  6. data/docs/bind-array-to-in_cond.md +1 -1
  7. data/docs/install-instant-client.md +2 -1
  8. data/docs/install-on-osx.md +29 -116
  9. data/docs/ldap-auth-and-function-interposition.md +123 -0
  10. data/docs/number-type-mapping.md +79 -0
  11. data/ext/oci8/apiwrap.c.tmpl +2 -5
  12. data/ext/oci8/apiwrap.rb +6 -1
  13. data/ext/oci8/apiwrap.yml +34 -22
  14. data/ext/oci8/attr.c +4 -2
  15. data/ext/oci8/bind.c +366 -6
  16. data/ext/oci8/connection_pool.c +3 -3
  17. data/ext/oci8/error.c +18 -33
  18. data/ext/oci8/extconf.rb +7 -4
  19. data/ext/oci8/hook_funcs.c +128 -51
  20. data/ext/oci8/lob.c +31 -75
  21. data/ext/oci8/metadata.c +2 -2
  22. data/ext/oci8/object.c +72 -27
  23. data/ext/oci8/oci8.c +27 -119
  24. data/ext/oci8/oci8.h +21 -3
  25. data/ext/oci8/oci8lib.c +50 -37
  26. data/ext/oci8/ocihandle.c +2 -2
  27. data/ext/oci8/ocinumber.c +22 -16
  28. data/ext/oci8/oraconf.rb +130 -257
  29. data/ext/oci8/oradate.c +1 -1
  30. data/ext/oci8/plthook_elf.c +384 -300
  31. data/ext/oci8/plthook_osx.c +10 -10
  32. data/ext/oci8/stmt.c +51 -16
  33. data/ext/oci8/win32.c +4 -22
  34. data/lib/oci8/bindtype.rb +1 -15
  35. data/lib/oci8/check_load_error.rb +57 -10
  36. data/lib/oci8/cursor.rb +48 -17
  37. data/lib/oci8/metadata.rb +9 -1
  38. data/lib/oci8/object.rb +10 -0
  39. data/lib/oci8/oci8.rb +26 -25
  40. data/lib/oci8/oracle_version.rb +11 -1
  41. data/lib/oci8/version.rb +1 -1
  42. data/lib/oci8.rb +11 -4
  43. data/lib/ruby-oci8.rb +0 -3
  44. data/ruby-oci8.gemspec +2 -3
  45. data/setup.rb +11 -2
  46. data/test/README.md +37 -0
  47. data/test/config.rb +1 -1
  48. data/test/setup_test_object.sql +21 -13
  49. data/test/setup_test_package.sql +59 -0
  50. data/test/test_all.rb +1 -0
  51. data/test/test_bind_boolean.rb +99 -0
  52. data/test/test_break.rb +11 -9
  53. data/test/test_clob.rb +4 -16
  54. data/test/test_datetime.rb +8 -3
  55. data/test/test_object.rb +33 -9
  56. data/test/test_oci8.rb +169 -45
  57. data/test/test_oranumber.rb +12 -6
  58. data/test/test_package_type.rb +15 -3
  59. data/test/test_properties.rb +17 -0
  60. metadata +40 -57
  61. data/docs/osx-install-dev-tools.png +0 -0
  62. data/test/README +0 -42
@@ -2,7 +2,7 @@
2
2
  /*
3
3
  * hook.c
4
4
  *
5
- * Copyright (C) 2015 Kubo Takehiro <kubo@jiubao.org>
5
+ * Copyright (C) 2015-2018 Kubo Takehiro <kubo@jiubao.org>
6
6
  */
7
7
  #if defined(_WIN32) || defined(__CYGWIN__)
8
8
  #define WINDOWS
@@ -12,15 +12,19 @@
12
12
  #include "plthook.h"
13
13
  #ifdef __CYGWIN__
14
14
  #undef boolean /* boolean defined in oratypes.h coflicts with that in windows.h */
15
+ #define stricmp strcasecmp
16
+ #define strnicmp strncasecmp
15
17
  #endif
16
18
  #ifdef WINDOWS
17
19
  #include <windows.h>
18
20
  #include <mstcpip.h>
21
+ #include <tlhelp32.h>
19
22
  #else
20
23
  #include <unistd.h>
21
24
  #include <sys/socket.h>
22
25
  #include <netinet/in.h>
23
26
  #include <netinet/tcp.h>
27
+ #include <dlfcn.h>
24
28
  #endif
25
29
 
26
30
  #ifdef WINDOWS
@@ -59,6 +63,7 @@ static int WSAAPI hook_setsockopt(SOCKET sockfd, int level, int optname, const v
59
63
  int oci8_tcp_keepalive_time = -1;
60
64
  #endif
61
65
 
66
+ static char hook_errmsg[512];
62
67
 
63
68
  typedef struct {
64
69
  const char *func_name;
@@ -95,35 +100,35 @@ static void socket_entry_clear(socket_entry_t *entry)
95
100
  UNLOCK(&lock);
96
101
  }
97
102
 
98
- static int replace_functions(const char * const *files, hook_func_entry_t *functions)
103
+ static int replace_functions(void *addr, const char *file, hook_func_entry_t *functions)
99
104
  {
105
+ plthook_t *ph;
100
106
  int i;
107
+ int rv = 0;
101
108
 
102
- for (i = 0; files[i] != NULL; i++) {
103
- const char *file = files[i];
104
- plthook_t *ph;
105
- if (plthook_open(&ph, file) == 0) {
106
- int j;
107
- int rv = 0;
108
-
109
- /* install hooks */
110
- for (j = 0; functions[j].func_name != NULL ; j++) {
111
- hook_func_entry_t *function = &functions[j];
112
- rv = plthook_replace(ph, function->func_name, function->func_addr, &function->old_func_addr);
113
- if (rv != 0) {
114
- while (--j >= 0) {
115
- /*restore hooked fuction address */
116
- plthook_replace(ph, functions[j].func_name, functions[j].old_func_addr, NULL);
117
- }
118
- plthook_close(ph);
119
- rb_raise(rb_eRuntimeError, "Could not replace function %s in %s", function->func_name, file);
120
- }
109
+ if (plthook_open_by_address(&ph, addr) != 0) {
110
+ strncpy(hook_errmsg, plthook_error(), sizeof(hook_errmsg) - 1);
111
+ hook_errmsg[sizeof(hook_errmsg) - 1] = '\0';
112
+ return -1;
113
+ }
114
+
115
+ /* install hooks */
116
+ for (i = 0; functions[i].func_name != NULL ; i++) {
117
+ hook_func_entry_t *function = &functions[i];
118
+ rv = plthook_replace(ph, function->func_name, function->func_addr, &function->old_func_addr);
119
+ if (rv != 0) {
120
+ strncpy(hook_errmsg, plthook_error(), sizeof(hook_errmsg) - 1);
121
+ hook_errmsg[sizeof(hook_errmsg) - 1] = '\0';
122
+ while (--i >= 0) {
123
+ /*restore hooked fuction address */
124
+ plthook_replace(ph, functions[i].func_name, functions[i].old_func_addr, NULL);
121
125
  }
122
- plthook_close(ph);
123
- return 0;
126
+ snprintf(hook_errmsg, sizeof(hook_errmsg), "Could not replace function %s in %s", function->func_name, file);
127
+ break;
124
128
  }
125
129
  }
126
- return -1;
130
+ plthook_close(ph);
131
+ return rv;
127
132
  }
128
133
 
129
134
  #ifdef WINDOWS
@@ -142,23 +147,6 @@ static int locK_is_initialized;
142
147
 
143
148
  static int WSAAPI hook_WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
144
149
 
145
- static const char * const tcp_func_files[] = {
146
- /* full client */
147
- "orantcp12.dll",
148
- "orantcp11.dll",
149
- "orantcp10.dll",
150
- "orantcp9.dll",
151
- /* instant client basic */
152
- "oraociei12.dll",
153
- "oraociei11.dll",
154
- "oraociei10.dll",
155
- /* instant client basic lite */
156
- "oraociicus12.dll",
157
- "oraociicus11.dll",
158
- "oraociicus10.dll",
159
- NULL,
160
- };
161
-
162
150
  static hook_func_entry_t tcp_functions[] = {
163
151
  {"WSARecv", (void*)hook_WSARecv, NULL},
164
152
  {"setsockopt", (void*)hook_setsockopt, NULL},
@@ -182,6 +170,38 @@ static int WSAAPI hook_WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount
182
170
  return rv;
183
171
  }
184
172
 
173
+ static int is_target_dll(MODULEENTRY32 *me)
174
+ {
175
+ static const char *basenames[] = {
176
+ "orantcp", // ORACLE_HOME-based client
177
+ "oraociei", // instant client basic
178
+ "oraociicus", // instant client basic lite
179
+ NULL,
180
+ };
181
+ const char **basename = basenames;
182
+ while (*basename != NULL) {
183
+ if (strnicmp(me->szModule, *basename, strlen(*basename)) == 0) {
184
+ break;
185
+ }
186
+ basename++;
187
+ }
188
+ if (*basename == NULL) {
189
+ return 0;
190
+ }
191
+ // basename{zero_or_more_digits}.dll
192
+ const char *p = me->szModule + strlen(*basename);
193
+ while ('0' <= *p && *p <= '9') {
194
+ p++;
195
+ }
196
+ if (stricmp(p, ".dll") != 0) {
197
+ return 0;
198
+ }
199
+ if (GetProcAddress((HMODULE)me->modBaseAddr, "nttini") == NULL) {
200
+ return 0;
201
+ }
202
+ return 1;
203
+ }
204
+
185
205
  void oci8_install_hook_functions()
186
206
  {
187
207
  static int hook_functions_installed = 0;
@@ -190,6 +210,9 @@ void oci8_install_hook_functions()
190
210
  DWORD data;
191
211
  DWORD cbData = sizeof(data);
192
212
  const char *reg_key = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
213
+ HANDLE hSnapshot;
214
+ MODULEENTRY32 me;
215
+ BOOL module_found = FALSE;
193
216
 
194
217
  if (hook_functions_installed) {
195
218
  return;
@@ -222,7 +245,21 @@ void oci8_install_hook_functions()
222
245
  }
223
246
  RegCloseKey(hKey);
224
247
 
225
- if (replace_functions(tcp_func_files, tcp_functions) != 0) {
248
+ hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
249
+ me.dwSize = sizeof(me);
250
+ if (Module32First(hSnapshot, &me)) {
251
+ do {
252
+ if (is_target_dll(&me)) {
253
+ module_found = TRUE;
254
+ if (replace_functions(me.modBaseAddr, me.szExePath, tcp_functions) != 0) {
255
+ CloseHandle(hSnapshot);
256
+ rb_raise(rb_eRuntimeError, "Hook error: %s", hook_errmsg);
257
+ }
258
+ }
259
+ } while (Module32Next(hSnapshot, &me));
260
+ }
261
+ CloseHandle(hSnapshot);
262
+ if (!module_found) {
226
263
  rb_raise(rb_eRuntimeError, "No DLL is found to hook.");
227
264
  }
228
265
  hook_functions_installed = 1;
@@ -247,14 +284,6 @@ static ssize_t hook_read(int fd, void *buf, size_t count);
247
284
  #define SO_EXT "so"
248
285
  #endif
249
286
 
250
- static const char * const files[] = {
251
- "libclntsh." SO_EXT ".12.1",
252
- "libclntsh." SO_EXT ".11.1",
253
- "libclntsh." SO_EXT ".10.1",
254
- "libclntsh." SO_EXT ".9.0",
255
- NULL,
256
- };
257
-
258
287
  static hook_func_entry_t functions[] = {
259
288
  {"read", (void*)hook_read, NULL},
260
289
  #ifdef SUPPORT_TCP_KEEPALIVE_TIME
@@ -279,16 +308,64 @@ static ssize_t hook_read(int fd, void *buf, size_t count)
279
308
  return rv;
280
309
  }
281
310
 
311
+ static void *ocifunc_addr(void *dlsym_handle, const char **file)
312
+ {
313
+ void *addr = dlsym(dlsym_handle, "OCIEnvCreate");
314
+ Dl_info dli;
315
+
316
+ if (addr == NULL) {
317
+ return NULL;
318
+ }
319
+ if (dladdr(addr, &dli) == 0) {
320
+ return NULL;
321
+ }
322
+ if (strstr(dli.dli_fname, "/libclntsh." SO_EXT) == NULL) {
323
+ return NULL;
324
+ }
325
+ *file = dli.dli_fname;
326
+ return addr;
327
+ }
328
+
329
+ #ifdef __linux__
330
+ #include <link.h>
331
+ static void *ocifunc_addr_linux(const char **file)
332
+ {
333
+ struct link_map *lm;
334
+ for (lm = _r_debug.r_map; lm != NULL; lm = lm->l_next) {
335
+ if (strstr(lm->l_name, "/libclntsh." SO_EXT) != NULL) {
336
+ *file = lm->l_name;
337
+ return (void*)lm->l_addr;
338
+ }
339
+ }
340
+ return NULL;
341
+ }
342
+ #endif
343
+
282
344
  void oci8_install_hook_functions(void)
283
345
  {
284
346
  static int hook_functions_installed = 0;
347
+ void *addr;
348
+ const char *file;
285
349
 
286
350
  if (hook_functions_installed) {
287
351
  return;
288
352
  }
289
- if (replace_functions(files, functions) != 0) {
353
+ addr = ocifunc_addr(RTLD_DEFAULT, &file);
354
+ if (addr == NULL) {
355
+ /* OCI symbols may be hooked by LD_PRELOAD. */
356
+ addr = ocifunc_addr(RTLD_NEXT, &file);
357
+ }
358
+ #ifdef __linux__
359
+ if (addr == NULL) {
360
+ addr = ocifunc_addr_linux(&file);
361
+ }
362
+ #endif
363
+ if (addr == NULL) {
290
364
  rb_raise(rb_eRuntimeError, "No shared library is found to hook.");
291
365
  }
366
+ if (replace_functions(addr, file, functions) != 0) {
367
+ rb_raise(rb_eRuntimeError, "Hook error: %s", hook_errmsg);
368
+ }
292
369
  hook_functions_installed = 1;
293
370
  }
294
371
 
data/ext/oci8/lob.c CHANGED
@@ -26,8 +26,6 @@ static VALUE seek_end;
26
26
 
27
27
  enum state {
28
28
  S_NO_OPEN_CLOSE,
29
- S_OPEN,
30
- S_CLOSE,
31
29
  S_BFILE_CLOSE,
32
30
  S_BFILE_OPEN,
33
31
  };
@@ -266,28 +264,6 @@ static ub8 oci8_lob_get_length(oci8_lob_t *lob)
266
264
  return len;
267
265
  }
268
266
 
269
- static void lob_open(oci8_lob_t *lob)
270
- {
271
- if (lob->state == S_CLOSE) {
272
- oci8_svcctx_t *svcctx = check_svcctx(lob);
273
-
274
- chker2(OCILobOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_DEFAULT),
275
- &svcctx->base);
276
- lob->state = S_OPEN;
277
- }
278
- }
279
-
280
- static void lob_close(oci8_lob_t *lob)
281
- {
282
- if (lob->state == S_OPEN) {
283
- oci8_svcctx_t *svcctx = check_svcctx(lob);
284
-
285
- chker2(OCILobClose_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob),
286
- &svcctx->base);
287
- lob->state = S_CLOSE;
288
- }
289
- }
290
-
291
267
  static void bfile_close(oci8_lob_t *lob)
292
268
  {
293
269
  if (lob->state == S_BFILE_OPEN) {
@@ -368,7 +344,6 @@ static void bfile_close(oci8_lob_t *lob)
368
344
  static VALUE oci8_lob_close(VALUE self)
369
345
  {
370
346
  oci8_lob_t *lob = TO_LOB(self);
371
- lob_close(lob);
372
347
  oci8_base_free(&lob->base);
373
348
  return self;
374
349
  }
@@ -591,7 +566,6 @@ static VALUE oci8_lob_truncate(VALUE self, VALUE len)
591
566
  oci8_lob_t *lob = TO_LOB(self);
592
567
  oci8_svcctx_t *svcctx = check_svcctx(lob);
593
568
 
594
- lob_open(lob);
595
569
  chker2(OCILobTrim2_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, NUM2ULL(len)),
596
570
  &svcctx->base);
597
571
  return self;
@@ -665,10 +639,9 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
665
639
  {
666
640
  oci8_lob_t *lob = TO_LOB(self);
667
641
  oci8_svcctx_t *svcctx = check_svcctx(lob);
668
- ub8 lob_length;
669
- ub8 read_len;
670
642
  ub8 pos = lob->pos;
671
- long strbufsiz;
643
+ long strbufsiz = 512;
644
+ ub8 sz;
672
645
  ub8 byte_amt;
673
646
  ub8 char_amt;
674
647
  sword rv;
@@ -678,36 +651,21 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
678
651
  ub1 piece = OCI_FIRST_PIECE;
679
652
 
680
653
  rb_scan_args(argc, argv, "01", &size);
681
- lob_length = oci8_lob_get_length(lob);
682
- if (lob_length == 0 && NIL_P(size)) {
683
- return rb_usascii_str_new("", 0);
684
- }
685
- if (lob_length <= pos) /* EOF */
686
- return Qnil;
687
654
  if (NIL_P(size)) {
688
- read_len = lob_length - pos;
655
+ sz = UB4MAXVAL;
689
656
  } else {
690
- ub8 sz = NUM2ULL(size);
691
- read_len = MIN(sz, lob_length - pos);
657
+ sz = NUM2ULL(size);
658
+ }
659
+ if (lob->state == S_BFILE_CLOSE) {
660
+ open_bfile(svcctx, lob, errhp);
692
661
  }
662
+ read_more_data:
693
663
  if (lob->lobtype == OCI_TEMP_CLOB) {
694
664
  byte_amt = 0;
695
- char_amt = read_len;
696
- if (oci8_nls_ratio == 1) {
697
- strbufsiz = MIN(read_len, ULONG_MAX);
698
- } else {
699
- strbufsiz = MIN(read_len + read_len / 8, ULONG_MAX);
700
- }
701
- if (strbufsiz <= 10) {
702
- strbufsiz = 10;
703
- }
665
+ char_amt = sz;
704
666
  } else {
705
- byte_amt = read_len;
667
+ byte_amt = sz;
706
668
  char_amt = 0;
707
- strbufsiz = MIN(read_len, ULONG_MAX);
708
- }
709
- if (lob->state == S_BFILE_CLOSE) {
710
- open_bfile(svcctx, lob, errhp);
711
669
  }
712
670
  do {
713
671
  VALUE strbuf = rb_str_buf_new(strbufsiz);
@@ -737,23 +695,30 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
737
695
  }
738
696
  rb_str_set_len(strbuf, byte_amt);
739
697
  rb_ary_push(v, strbuf);
698
+ if (strbufsiz < 128 * 1024 * 1024) {
699
+ strbufsiz *= 2;
700
+ }
740
701
  } while (rv == OCI_NEED_DATA);
741
702
 
742
- if (pos >= lob_length) {
743
- lob_close(lob);
744
- bfile_close(lob);
703
+ if (NIL_P(size) && pos - lob->pos == sz) {
704
+ lob->pos = pos;
705
+ piece = OCI_FIRST_PIECE;
706
+ goto read_more_data;
745
707
  }
746
708
  lob->pos = pos;
747
709
  switch (RARRAY_LEN(v)) {
748
710
  case 0:
749
- return Qnil;
711
+ if (NIL_P(size) && pos == 0) {
712
+ return rb_usascii_str_new("", 0);
713
+ } else {
714
+ return Qnil;
715
+ }
750
716
  case 1:
751
717
  v = RARRAY_AREF(v, 0);
752
718
  break;
753
719
  default:
754
720
  v = rb_ary_join(v, Qnil);
755
721
  }
756
- OBJ_TAINT(v);
757
722
  if (lob->lobtype == OCI_TEMP_CLOB) {
758
723
  /* set encoding */
759
724
  rb_enc_associate(v, oci8_encoding);
@@ -781,7 +746,6 @@ static VALUE oci8_lob_write(VALUE self, VALUE data)
781
746
  ub8 byte_amt;
782
747
  ub8 char_amt;
783
748
 
784
- lob_open(lob);
785
749
  if (TYPE(data) != T_STRING) {
786
750
  str = rb_obj_as_string(data);
787
751
  } else {
@@ -801,48 +765,40 @@ static VALUE oci8_lob_write(VALUE self, VALUE data)
801
765
  RB_GC_GUARD(str);
802
766
  if (lob->lobtype == OCI_TEMP_CLOB) {
803
767
  lob->pos += char_amt;
804
- return UINT2NUM(char_amt);
768
+ return ULL2NUM(char_amt);
805
769
  } else {
806
770
  lob->pos += byte_amt;
807
- return UINT2NUM(byte_amt);
771
+ return ULL2NUM(byte_amt);
808
772
  }
809
773
  }
810
774
 
811
775
  /*
812
- * @deprecated I'm not sure that this is what the name indicates.
776
+ * @deprecated LOB#sync had not worked by mistake. Do nothing now.
813
777
  * @private
814
778
  */
815
779
  static VALUE oci8_lob_get_sync(VALUE self)
816
780
  {
817
- oci8_lob_t *lob = TO_LOB(self);
818
- return (lob->state == S_NO_OPEN_CLOSE) ? Qtrue : Qfalse;
781
+ rb_warning("LOB#sync had not worked by mistake. Do nothing now.");
782
+ return Qfalse;
819
783
  }
820
784
 
821
785
  /*
822
- * @deprecated I'm not sure that this is what the name indicates.
786
+ * @deprecated LOB#sync had not worked by mistake. Do nothing now.
823
787
  * @private
824
788
  */
825
789
  static VALUE oci8_lob_set_sync(VALUE self, VALUE b)
826
790
  {
827
- oci8_lob_t *lob = TO_LOB(self);
828
- if (RTEST(b)) {
829
- lob_close(lob);
830
- lob->state = S_NO_OPEN_CLOSE;
831
- } else {
832
- if (lob->state == S_NO_OPEN_CLOSE)
833
- lob->state = S_CLOSE;
834
- }
791
+ rb_warning("LOB#sync had not worked by mistake. Do nothing now.");
835
792
  return b;
836
793
  }
837
794
 
838
795
  /*
839
- * @deprecated I'm not sure that this is what the name indicates.
796
+ * @deprecated LOB#flush had not worked by mistake. Do nothing now.
840
797
  * @private
841
798
  */
842
799
  static VALUE oci8_lob_flush(VALUE self)
843
800
  {
844
- oci8_lob_t *lob = TO_LOB(self);
845
- lob_close(lob);
801
+ rb_warning("LOB#flush had not worked by mistake. Do nothing now.");
846
802
  return self;
847
803
  }
848
804
 
data/ext/oci8/metadata.c CHANGED
@@ -195,7 +195,7 @@ VALUE oci8_do_describe(VALUE self, void *objptr, ub4 objlen, ub1 objtype, VALUE
195
195
  static VALUE oci8_describe(VALUE self, VALUE name, VALUE klass, VALUE check_public)
196
196
  {
197
197
  char *str;
198
- size_t idx, len;
198
+ int idx, len;
199
199
  VALUE metadata;
200
200
  VALUE obj_link = Qnil;
201
201
 
@@ -204,7 +204,7 @@ static VALUE oci8_describe(VALUE self, VALUE name, VALUE klass, VALUE check_publ
204
204
  rb_raise(rb_eArgError, "empty string is set.");
205
205
  }
206
206
  str = RSTRING_PTR(name);
207
- len = RSTRING_LEN(name);
207
+ len = RSTRING_LENINT(name);
208
208
  for (idx = 0; idx < len; idx++) {
209
209
  if (str[idx] == '@') {
210
210
  obj_link = rb_enc_str_new(str + idx + 1, len - idx - 1, oci8_encoding);