ruby-oci8 2.2.12 → 2.2.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  /* -*- indent-tabs-mode: nil -*-
2
2
  *
3
- * plthook_win32.c -- implemention of plthook for PE format
3
+ * plthook_win32.c -- implementation of plthook for PE format
4
4
  *
5
5
  * URL: https://github.com/kubo/plthook
6
6
  *
@@ -86,7 +86,7 @@ int plthook_open(plthook_t **plthook_out, const char *filename)
86
86
  HMODULE hMod;
87
87
 
88
88
  *plthook_out = NULL;
89
- if (!GetModuleHandleExA(0, filename, &hMod)) {
89
+ if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, filename, &hMod)) {
90
90
  set_errmsg2("Cannot get module %s: ", filename);
91
91
  return PLTHOOK_FILE_NOT_FOUND;
92
92
  }
@@ -107,7 +107,7 @@ int plthook_open_by_address(plthook_t **plthook_out, void *address)
107
107
  HMODULE hMod;
108
108
 
109
109
  *plthook_out = NULL;
110
- if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, address, &hMod)) {
110
+ if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, address, &hMod)) {
111
111
  set_errmsg2("Cannot get module at address %p: ", address);
112
112
  return PLTHOOK_FILE_NOT_FOUND;
113
113
  }
@@ -134,7 +134,8 @@ static int plthook_open_real(plthook_t **plthook_out, HMODULE hMod)
134
134
  for (desc = desc_head; desc->Name != 0; desc++) {
135
135
  IMAGE_THUNK_DATA *name_thunk = (IMAGE_THUNK_DATA*)((char*)hMod + desc->OriginalFirstThunk);
136
136
  IMAGE_THUNK_DATA *addr_thunk = (IMAGE_THUNK_DATA*)((char*)hMod + desc->FirstThunk);
137
- int is_winsock2_dll = (stricmp((char *)hMod + desc->Name, "WS2_32.DLL") == 0);
137
+ const char *module_name = (char *)hMod + desc->Name;
138
+ int is_winsock2_dll = (stricmp(module_name, "WS2_32.DLL") == 0);
138
139
 
139
140
  while (addr_thunk->u1.Function != 0) {
140
141
  if (IMAGE_SNAP_BY_ORDINAL(name_thunk->u1.Ordinal)) {
@@ -144,8 +145,11 @@ static int plthook_open_real(plthook_t **plthook_out, HMODULE hMod)
144
145
  name = winsock2_ordinal2name(ordinal);
145
146
  }
146
147
  if (name == NULL) {
147
- char buf[64];
148
- ordinal_name_buflen += sprintf(buf, "#%d", ordinal) + 1;
148
+ #ifdef __CYGWIN__
149
+ ordinal_name_buflen += snprintf(NULL, 0, "%s:@%d", module_name, ordinal) + 1;
150
+ #else
151
+ ordinal_name_buflen += _scprintf("%s:@%d", module_name, ordinal) + 1;
152
+ #endif
149
153
  }
150
154
  }
151
155
  num_entries++;
@@ -167,7 +171,8 @@ static int plthook_open_real(plthook_t **plthook_out, HMODULE hMod)
167
171
  for (desc = desc_head; desc->Name != 0; desc++) {
168
172
  IMAGE_THUNK_DATA *name_thunk = (IMAGE_THUNK_DATA*)((char*)hMod + desc->OriginalFirstThunk);
169
173
  IMAGE_THUNK_DATA *addr_thunk = (IMAGE_THUNK_DATA*)((char*)hMod + desc->FirstThunk);
170
- int is_winsock2_dll = (stricmp((char *)hMod + desc->Name, "WS2_32.DLL") == 0);
174
+ const char *module_name = (char *)hMod + desc->Name;
175
+ int is_winsock2_dll = (stricmp(module_name, "WS2_32.DLL") == 0);
171
176
 
172
177
  while (addr_thunk->u1.Function != 0) {
173
178
  const char *name = NULL;
@@ -178,12 +183,13 @@ static int plthook_open_real(plthook_t **plthook_out, HMODULE hMod)
178
183
  name = winsock2_ordinal2name(ordinal);
179
184
  }
180
185
  if (name == NULL) {
181
- ordinal_name_buf += sprintf(ordinal_name_buf, "#%d", ordinal) + 1;
186
+ name = ordinal_name_buf;
187
+ ordinal_name_buf += sprintf(ordinal_name_buf, "%s:@%d", module_name, ordinal) + 1;
182
188
  }
183
189
  } else {
184
190
  name = (char*)((PIMAGE_IMPORT_BY_NAME)((char*)hMod + name_thunk->u1.AddressOfData))->Name;
185
191
  }
186
- plthook->entries[idx].mod_name = (char *)hMod + desc->Name;
192
+ plthook->entries[idx].mod_name = module_name;
187
193
  plthook->entries[idx].name = name;
188
194
  plthook->entries[idx].addr = (void**)&addr_thunk->u1.Function;
189
195
  idx++;
@@ -231,41 +237,49 @@ int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, vo
231
237
  const char *name;
232
238
  void **addr;
233
239
  int rv;
240
+ BOOL import_by_ordinal = funcname[0] != '?' && strstr(funcname, ":@") != NULL;
234
241
 
235
242
  if (plthook == NULL) {
236
243
  set_errmsg("invalid argument: The first argument is null.");
237
244
  return PLTHOOK_INVALID_ARGUMENT;
238
245
  }
239
246
  while ((rv = plthook_enum(plthook, &pos, &name, &addr)) == 0) {
247
+ if (import_by_ordinal) {
248
+ if (stricmp(name, funcname) == 0) {
249
+ goto found;
250
+ }
251
+ } else {
252
+ /* import by name */
240
253
  #ifdef _WIN64
241
- if (strcmp(name, funcname) == 0) {
242
- replace_funcaddr(addr, funcaddr, oldfunc);
243
- return 0;
244
- }
245
- #else
246
- /* Function names may be decorated in Windows 32-bit applications. */
247
- if (strncmp(name, funcname, funcnamelen) == 0) {
248
- if (name[funcnamelen] == '\0' || name[funcnamelen] == '@') {
249
- replace_funcaddr(addr, funcaddr, oldfunc);
250
- return 0;
254
+ if (strcmp(name, funcname) == 0) {
255
+ goto found;
251
256
  }
252
- }
253
- if (name[0] == '_' || name[0] == '@') {
254
- name++;
257
+ #else
258
+ /* Function names may be decorated in Windows 32-bit applications. */
255
259
  if (strncmp(name, funcname, funcnamelen) == 0) {
256
260
  if (name[funcnamelen] == '\0' || name[funcnamelen] == '@') {
257
- replace_funcaddr(addr, funcaddr, oldfunc);
258
- return 0;
261
+ goto found;
262
+ }
263
+ }
264
+ if (name[0] == '_' || name[0] == '@') {
265
+ name++;
266
+ if (strncmp(name, funcname, funcnamelen) == 0) {
267
+ if (name[funcnamelen] == '\0' || name[funcnamelen] == '@') {
268
+ goto found;
269
+ }
259
270
  }
260
271
  }
261
- }
262
272
  #endif
273
+ }
263
274
  }
264
275
  if (rv == EOF) {
265
276
  set_errmsg("no such function: %s", funcname);
266
277
  rv = PLTHOOK_FUNCTION_NOT_FOUND;
267
278
  }
268
279
  return rv;
280
+ found:
281
+ replace_funcaddr(addr, funcaddr, oldfunc);
282
+ return 0;
269
283
  }
270
284
 
271
285
  void plthook_close(plthook_t *plthook)
@@ -127,7 +127,15 @@ class OCI8
127
127
  #
128
128
  # @return [String]
129
129
  def to_s
130
- format('%d.%d.%d.%d.%d', @major, @minor, @update, @patch, @port_update)
130
+ version_format =
131
+ if @major >= 23 && @patch != 0 && @port_update != 0
132
+ # The fifth numeral is the release month (01 through 12) since Oracle 23ai
133
+ # See https://docs.oracle.com/en/database/oracle/oracle-database/23/upgrd/oracle-database-release-numbers.html#GUID-1E2F3945-C0EE-4EB2-A933-8D1862D8ECE2__GUID-704EC7BB-4EEA-4A92-96FC-579B216DCA97
134
+ '%d.%d.%d.%d.%02d'
135
+ else
136
+ '%d.%d.%d.%d.%d'
137
+ end
138
+ format(version_format, @major, @minor, @update, @patch, @port_update)
131
139
  end
132
140
 
133
141
  # Returns true if +self+ and +other+ are the same type and have
data/lib/oci8/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class OCI8
2
- VERSION = "2.2.12"
2
+ VERSION = "2.2.13"
3
3
  end
data/lib/oci8.rb CHANGED
@@ -147,6 +147,8 @@ class OCI8
147
147
  ORAVER_12_1 = OCI8::OracleVersion.new(12, 1)
148
148
  # @private
149
149
  ORAVER_18 = OCI8::OracleVersion.new(18)
150
+ # @private
151
+ ORAVER_23 = OCI8::OracleVersion.new(23)
150
152
 
151
153
  # @private
152
154
  @@oracle_client_version = OCI8::OracleVersion.new(self.oracle_client_vernum)
@@ -1896,6 +1896,7 @@ EOS
1896
1896
  # Get data_size of NCHAR(1) and that of CHAR(1 CHAR).
1897
1897
  # They depend on the database character set and the
1898
1898
  # client character set.
1899
+ drop_table('test_table')
1899
1900
  @conn.exec('CREATE TABLE test_table (nc NCHAR(1), c CHAR(1 CHAR))')
1900
1901
  cursor = @conn.exec("select * from test_table")
1901
1902
  cfrm = cursor.column_metadata[0].data_size # size of NCHAR(1) in bytes
@@ -697,7 +697,9 @@ EOS
697
697
  OraNumber.new(str)
698
698
  flunk("exception expected but none was thrown. test data: " + str)
699
699
  rescue
700
- assert_equal(oraerr.to_s, $!.to_s, "test data: " + str)
700
+ expected_errhead = oraerr.to_s.gsub(/:.*/m, '') # strip chars after ':'
701
+ actual_errhead = $!.to_s.gsub(/:.*/m, '')
702
+ assert_equal(expected_errhead, actual_errhead, "test data: " + str)
701
703
  end
702
704
  end
703
705
  if onum
@@ -47,6 +47,12 @@ class TestPackageType < Minitest::Test
47
47
  end
48
48
 
49
49
  def test_describe_package
50
+ if $oracle_server_version >= OCI8::ORAVER_23
51
+ boolean_type_name = 'BOOLEAN'
52
+ else
53
+ boolean_type_name = 'PL/SQL BOOLEAN'
54
+ end
55
+
50
56
  integer_type_attrs = {
51
57
  :class => OCI8::Metadata::Type,
52
58
  #:typecode => nil,
@@ -127,7 +133,7 @@ class TestPackageType < Minitest::Test
127
133
  #:map_method => nil,
128
134
  #:order_method => nil,
129
135
  :is_invoker_rights? => false,
130
- :name => 'PL/SQL BOOLEAN',
136
+ :name => boolean_type_name,
131
137
  :schema_name => 'SYS',
132
138
  :is_final_type? => true,
133
139
  :is_instantiable_type? => true,
@@ -137,7 +143,7 @@ class TestPackageType < Minitest::Test
137
143
  :package_name => nil,
138
144
  :type_attrs => [],
139
145
  #:type_methods => [],
140
- :inspect => '#<OCI8::Metadata::Type:(0) SYS.PL/SQL BOOLEAN>', # TODO: change to "BOOLEAN"
146
+ :inspect => "#<OCI8::Metadata::Type:(0) SYS.#{boolean_type_name}>",
141
147
  }
142
148
 
143
149
  varchar2_type_attrs = {
@@ -277,7 +283,7 @@ class TestPackageType < Minitest::Test
277
283
  :num_elems => 0,
278
284
  :precision => 0,
279
285
  :scale => 0,
280
- :type_name => 'PL/SQL BOOLEAN',
286
+ :type_name => boolean_type_name,
281
287
  :schema_name => 'SYS',
282
288
  :type_metadata => boolean_type_attrs,
283
289
  :inspect => '#<OCI8::Metadata::Collection: BOOLEAN>',
@@ -444,7 +450,7 @@ class TestPackageType < Minitest::Test
444
450
  :name => 'B',
445
451
  :precision => 0,
446
452
  :scale => 0,
447
- :type_name => 'PL/SQL BOOLEAN',
453
+ :type_name => boolean_type_name,
448
454
  :schema_name => 'SYS',
449
455
  :fsprecision => 0,
450
456
  :lfprecision => 0,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-oci8
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.12
4
+ version: 2.2.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kubo Takehiro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-30 00:00:00.000000000 Z
11
+ date: 2024-07-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 'ruby-oci8 is a ruby interface for Oracle using OCI8 API. It is available
14
14
  with Oracle 10g or later including Oracle Instant Client.
@@ -152,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
152
  - !ruby/object:Gem::Version
153
153
  version: '0'
154
154
  requirements: []
155
- rubygems_version: 3.4.1
155
+ rubygems_version: 3.4.10
156
156
  signing_key:
157
157
  specification_version: 4
158
158
  summary: Ruby interface for Oracle using OCI8 API