geoip2_c 0.4.0 → 0.4.1
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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +23 -0
- data/.github/workflows/ubuntu.yml +17 -8
- data/.github/workflows/windows.yml +17 -7
- data/ext/geoip2/geoip2.c +82 -32
- data/lib/geoip2/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 25a17a86c77f7e092f8f24a224cd8a57d6bba8595f51d0e052e3a846a3fd67e8
|
|
4
|
+
data.tar.gz: 1bb129e6fba2ff42f583dff127ba4168d958c12af6a7c1521d23a07fbf59dab8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 22d90d27edebbf88c8d0a9ec2edc304fc0265b1f6814012ca47e4cd5b9ef5f8422fe3b92a63ed90bbba1f3a2eb874c98d1f52f9d28d246f8df83f5d19e3a4819
|
|
7
|
+
data.tar.gz: 4ba29b9f46963e6be9c298c686885b6224e4b7346069da485972d48ac91f0baf025fa882461df943461a0798102a3429cd165d7c13340c7c1aecae576e0fbf97
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: 'github-actions'
|
|
4
|
+
directory: '/'
|
|
5
|
+
schedule:
|
|
6
|
+
interval: 'monthly'
|
|
7
|
+
groups:
|
|
8
|
+
# PR: "Security update [package] from [old] to [new]"
|
|
9
|
+
# This PR should be merged in hurry
|
|
10
|
+
security-updates:
|
|
11
|
+
applies-to: security-updates
|
|
12
|
+
patterns:
|
|
13
|
+
- '*'
|
|
14
|
+
|
|
15
|
+
# PR: "Bump [package] from [old] to [new]"
|
|
16
|
+
# No need to be merged this PR in hurry. It is enough to merge
|
|
17
|
+
# once in a month.
|
|
18
|
+
monthly-updates:
|
|
19
|
+
applies-to: version-updates
|
|
20
|
+
patterns:
|
|
21
|
+
- '*'
|
|
22
|
+
# Allow to create PR both of security and normal updates.
|
|
23
|
+
open-pull-requests-limit: 1
|
|
@@ -1,24 +1,33 @@
|
|
|
1
1
|
name: ubuntu
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: '0 0 1 * *'
|
|
6
10
|
|
|
7
11
|
jobs:
|
|
12
|
+
ruby-versions:
|
|
13
|
+
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
|
|
14
|
+
with:
|
|
15
|
+
engine: cruby
|
|
16
|
+
min_version: 3.0
|
|
8
17
|
build:
|
|
18
|
+
needs: ruby-versions
|
|
9
19
|
runs-on: ubuntu-latest
|
|
10
20
|
strategy:
|
|
11
21
|
matrix:
|
|
12
|
-
ruby:
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
- "3.0"
|
|
22
|
+
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
|
|
23
|
+
exclude:
|
|
24
|
+
- ruby: head
|
|
16
25
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
26
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
18
27
|
with:
|
|
19
28
|
submodules: true
|
|
20
29
|
- name: Setup ruby
|
|
21
|
-
uses: ruby/setup-ruby@
|
|
30
|
+
uses: ruby/setup-ruby@0dafeac902942906541bc140009cdbf32665b601 # v1.315.0
|
|
22
31
|
with:
|
|
23
32
|
ruby-version: ${{ matrix.ruby }}
|
|
24
33
|
bundler: latest
|
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
name: windows
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: '0 0 1 * *'
|
|
6
10
|
|
|
7
11
|
jobs:
|
|
12
|
+
ruby-versions:
|
|
13
|
+
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
|
|
14
|
+
with:
|
|
15
|
+
engine: cruby
|
|
16
|
+
min_version: 3.1
|
|
8
17
|
build:
|
|
18
|
+
needs: ruby-versions
|
|
9
19
|
runs-on: windows-latest
|
|
10
20
|
strategy:
|
|
11
21
|
matrix:
|
|
12
|
-
ruby:
|
|
13
|
-
|
|
14
|
-
-
|
|
22
|
+
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
|
|
23
|
+
exclude:
|
|
24
|
+
- ruby: head
|
|
15
25
|
include:
|
|
16
26
|
- ruby: "3.0.3"
|
|
17
27
|
# On Ruby 3.0, we need to use fiddle 1.0.8 or later to retrieve correct
|
|
@@ -23,7 +33,7 @@ jobs:
|
|
|
23
33
|
# * https://github.com/oneclick/rubyinstaller2/blob/8225034c22152d8195bc0aabc42a956c79d6c712/lib/ruby_installer/build/dll_directory.rb
|
|
24
34
|
ruby-lib-opt: RUBYLIB=%RUNNER_TOOL_CACHE%/Ruby/3.0.3/x64/lib/ruby/gems/3.0.0/gems/fiddle-1.1.0/lib
|
|
25
35
|
steps:
|
|
26
|
-
- uses: actions/checkout@
|
|
36
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
27
37
|
with:
|
|
28
38
|
submodules: true
|
|
29
39
|
- name: Install dependencies
|
|
@@ -31,7 +41,7 @@ jobs:
|
|
|
31
41
|
ridk enable
|
|
32
42
|
pacman -Sy --noconfirm mingw-w64-x86_64-libmaxminddb
|
|
33
43
|
- name: Setup ruby
|
|
34
|
-
uses: ruby/setup-ruby@
|
|
44
|
+
uses: ruby/setup-ruby@0dafeac902942906541bc140009cdbf32665b601 # v1.315.0
|
|
35
45
|
with:
|
|
36
46
|
ruby-version: ${{ matrix.ruby }}
|
|
37
47
|
bundler: latest
|
data/ext/geoip2/geoip2.c
CHANGED
|
@@ -33,6 +33,23 @@ typedef struct {
|
|
|
33
33
|
bool symbolize_keys;
|
|
34
34
|
} ParseRequest;
|
|
35
35
|
|
|
36
|
+
/* A LookupResult holds a copy of the libmaxminddb lookup result (whose
|
|
37
|
+
* entry.mmdb points into the owning Database's MMDB_s) together with a
|
|
38
|
+
* reference to that Database VALUE. Keeping the reference and marking it
|
|
39
|
+
* prevents the Database (and its mmap'd file) from being freed while a
|
|
40
|
+
* LookupResult derived from it is still alive. */
|
|
41
|
+
typedef struct {
|
|
42
|
+
MMDB_lookup_result_s result;
|
|
43
|
+
VALUE db;
|
|
44
|
+
} LookupResult;
|
|
45
|
+
|
|
46
|
+
static void
|
|
47
|
+
lookup_result_mark(void *ptr)
|
|
48
|
+
{
|
|
49
|
+
LookupResult *lr = (LookupResult *)ptr;
|
|
50
|
+
rb_gc_mark(lr->db);
|
|
51
|
+
}
|
|
52
|
+
|
|
36
53
|
static const rb_data_type_t rb_mmdb_type = {
|
|
37
54
|
"geoip2/mmdb", {
|
|
38
55
|
0, mmdb_free, 0,
|
|
@@ -42,11 +59,25 @@ static const rb_data_type_t rb_mmdb_type = {
|
|
|
42
59
|
|
|
43
60
|
static const rb_data_type_t rb_lookup_result_type = {
|
|
44
61
|
"geoip2/lookup_result", {
|
|
45
|
-
|
|
62
|
+
lookup_result_mark, RUBY_DEFAULT_FREE, 0,
|
|
46
63
|
}, NULL, NULL,
|
|
47
64
|
RUBY_TYPED_FREE_IMMEDIATELY
|
|
48
65
|
};
|
|
49
66
|
|
|
67
|
+
/* Fetch the LookupResult and ensure its backing database is still usable.
|
|
68
|
+
* Raises rather than dereferencing a freed/unmapped MMDB_s (use-after-free). */
|
|
69
|
+
static LookupResult *
|
|
70
|
+
lookup_result_get_open(VALUE self)
|
|
71
|
+
{
|
|
72
|
+
LookupResult *lr;
|
|
73
|
+
TypedData_Get_Struct(self, LookupResult, &rb_lookup_result_type, lr);
|
|
74
|
+
if (lr->result.entry.mmdb == NULL ||
|
|
75
|
+
mmdb_is_closed((MMDB_s *)lr->result.entry.mmdb)) {
|
|
76
|
+
rb_raise(rb_eGeoIP2Error, "the database is closed");
|
|
77
|
+
}
|
|
78
|
+
return lr;
|
|
79
|
+
}
|
|
80
|
+
|
|
50
81
|
static void
|
|
51
82
|
mmdb_open(const char *db_path, MMDB_s *mmdb)
|
|
52
83
|
{
|
|
@@ -141,10 +172,20 @@ mmdb_entry_data_decode(MMDB_entry_data_s *entry_data)
|
|
|
141
172
|
case MMDB_DATA_TYPE_UINT64:
|
|
142
173
|
return UINT2NUM(entry_data->uint64);
|
|
143
174
|
case MMDB_DATA_TYPE_UINT128:
|
|
175
|
+
/* uint128 does not fit in a C unsigned long, so build the Integer from the
|
|
176
|
+
* full 128 bits instead of truncating it through UINT2NUM. */
|
|
144
177
|
#if !(MMDB_UINT128_IS_BYTE_ARRAY)
|
|
145
|
-
|
|
178
|
+
{
|
|
179
|
+
mmdb_uint128_t value = entry_data->uint128;
|
|
180
|
+
return rb_integer_unpack(&value, 1, sizeof(value), 0,
|
|
181
|
+
INTEGER_PACK_NATIVE_BYTE_ORDER |
|
|
182
|
+
INTEGER_PACK_LSWORD_FIRST);
|
|
183
|
+
}
|
|
146
184
|
#else
|
|
147
|
-
|
|
185
|
+
/* entry_data->uint128 is a big-endian uint8_t[16]. */
|
|
186
|
+
return rb_integer_unpack(entry_data->uint128, 16, 1, 0,
|
|
187
|
+
INTEGER_PACK_BIG_ENDIAN |
|
|
188
|
+
INTEGER_PACK_MSWORD_FIRST);
|
|
148
189
|
#endif
|
|
149
190
|
case MMDB_DATA_TYPE_ARRAY:
|
|
150
191
|
/* TODO: not implemented */
|
|
@@ -266,6 +307,14 @@ rb_geoip2_db_open_mmdb(VALUE self, VALUE path)
|
|
|
266
307
|
db_path = StringValueCStr(path);
|
|
267
308
|
|
|
268
309
|
TypedData_Get_Struct(self, struct MMDB_s, &rb_mmdb_type, mmdb);
|
|
310
|
+
|
|
311
|
+
/* Reopening over an already-open database would overwrite the MMDB_s in
|
|
312
|
+
* place and leak libmaxminddb's internal allocations (and the previous
|
|
313
|
+
* mmap). Close the current database first. */
|
|
314
|
+
if (!mmdb_is_closed(mmdb)) {
|
|
315
|
+
mmdb_close(mmdb);
|
|
316
|
+
}
|
|
317
|
+
|
|
269
318
|
mmdb_open(db_path, mmdb);
|
|
270
319
|
|
|
271
320
|
return Qnil;
|
|
@@ -291,7 +340,7 @@ rb_geoip2_db_lookup(VALUE self, VALUE ip)
|
|
|
291
340
|
char *ip_str;
|
|
292
341
|
MMDB_s *mmdb;
|
|
293
342
|
MMDB_lookup_result_s result;
|
|
294
|
-
|
|
343
|
+
LookupResult *result_ptr;
|
|
295
344
|
VALUE obj;
|
|
296
345
|
|
|
297
346
|
Check_Type(ip, T_STRING);
|
|
@@ -305,12 +354,11 @@ rb_geoip2_db_lookup(VALUE self, VALUE ip)
|
|
|
305
354
|
}
|
|
306
355
|
|
|
307
356
|
obj = TypedData_Make_Struct(rb_cGeoIP2LookupResult,
|
|
308
|
-
|
|
357
|
+
LookupResult,
|
|
309
358
|
&rb_lookup_result_type,
|
|
310
359
|
result_ptr);
|
|
311
|
-
result_ptr->
|
|
312
|
-
result_ptr->
|
|
313
|
-
result_ptr->netmask = result.netmask;
|
|
360
|
+
result_ptr->result = result;
|
|
361
|
+
result_ptr->db = self;
|
|
314
362
|
|
|
315
363
|
rb_iv_set(obj, "@symbolize_keys", rb_iv_get(self, "@symbolize_keys"));
|
|
316
364
|
|
|
@@ -321,11 +369,12 @@ static VALUE
|
|
|
321
369
|
rb_geoip2_lr_alloc(VALUE klass)
|
|
322
370
|
{
|
|
323
371
|
VALUE obj;
|
|
324
|
-
|
|
372
|
+
LookupResult *result;
|
|
325
373
|
obj = TypedData_Make_Struct(klass,
|
|
326
|
-
|
|
374
|
+
LookupResult,
|
|
327
375
|
&rb_lookup_result_type,
|
|
328
376
|
result);
|
|
377
|
+
result->db = Qnil;
|
|
329
378
|
return obj;
|
|
330
379
|
}
|
|
331
380
|
|
|
@@ -351,13 +400,15 @@ rb_geoip2_lr_get_value(int argc, VALUE *argv, VALUE self)
|
|
|
351
400
|
VALUE arg;
|
|
352
401
|
VALUE rest;
|
|
353
402
|
char **path;
|
|
403
|
+
VALUE path_tmp;
|
|
354
404
|
int i = 0;
|
|
355
|
-
|
|
405
|
+
LookupResult *result = NULL;
|
|
356
406
|
MMDB_entry_s entry;
|
|
357
407
|
MMDB_entry_data_s entry_data;
|
|
358
408
|
char *tmp;
|
|
359
409
|
VALUE e;
|
|
360
410
|
int status;
|
|
411
|
+
VALUE val;
|
|
361
412
|
|
|
362
413
|
rb_scan_args(argc, argv, "1*", &arg, &rest);
|
|
363
414
|
switch(TYPE(arg)) {
|
|
@@ -370,12 +421,14 @@ rb_geoip2_lr_get_value(int argc, VALUE *argv, VALUE self)
|
|
|
370
421
|
rb_raise(rb_eArgError, "Expected a String or a Symbol");
|
|
371
422
|
break;
|
|
372
423
|
}
|
|
373
|
-
path = malloc(sizeof(char *) * (RARRAY_LEN(rest) + 2));
|
|
374
424
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
425
|
+
result = lookup_result_get_open(self);
|
|
426
|
+
|
|
427
|
+
/* ALLOCV_N ties the allocation to path_tmp: it is released automatically even
|
|
428
|
+
* if a later key conversion raises (e.g. a non-String key, or a String with
|
|
429
|
+
* an embedded NUL that makes StringValueCStr raise), and it raises
|
|
430
|
+
* NoMemoryError instead of returning NULL on allocation failure. */
|
|
431
|
+
path = ALLOCV_N(char *, path_tmp, RARRAY_LEN(rest) + 2);
|
|
379
432
|
|
|
380
433
|
path[i] = rb_geoip2_lr_arg_convert_to_cstring(arg);
|
|
381
434
|
while (RARRAY_LEN(rest) != 0) {
|
|
@@ -387,18 +440,18 @@ rb_geoip2_lr_get_value(int argc, VALUE *argv, VALUE self)
|
|
|
387
440
|
|
|
388
441
|
path[i+1] = NULL;
|
|
389
442
|
|
|
390
|
-
entry = result->entry;
|
|
443
|
+
entry = result->result.entry;
|
|
391
444
|
|
|
392
445
|
status = MMDB_aget_value(&entry, &entry_data, (const char *const *const)path);
|
|
393
446
|
|
|
394
447
|
if (status != MMDB_SUCCESS) {
|
|
395
|
-
free(path);
|
|
396
448
|
/* fprintf(stderr, "%s:%s\n", __FUNCTION__, MMDB_strerror(status)); */
|
|
449
|
+
ALLOCV_END(path_tmp);
|
|
397
450
|
return Qnil;
|
|
398
451
|
}
|
|
399
452
|
|
|
400
453
|
if (!entry_data.has_data) {
|
|
401
|
-
|
|
454
|
+
ALLOCV_END(path_tmp);
|
|
402
455
|
return Qnil;
|
|
403
456
|
}
|
|
404
457
|
|
|
@@ -407,38 +460,38 @@ rb_geoip2_lr_get_value(int argc, VALUE *argv, VALUE self)
|
|
|
407
460
|
// FIXME optimize below code
|
|
408
461
|
VALUE array = rb_ary_new();
|
|
409
462
|
VALUE hash;
|
|
410
|
-
VALUE val;
|
|
411
463
|
bool symbolize_keys = RTEST(rb_iv_get(self, "@symbolize_keys"));
|
|
412
464
|
for (int j = 0; path[j] != NULL; j++) {
|
|
413
465
|
rb_ary_push(array, symbolize_keys ? ID2SYM(rb_intern(path[j])) : rb_str_new_cstr(path[j]));
|
|
414
466
|
}
|
|
415
467
|
hash = rb_funcall(self, rb_intern("to_h"), 0);
|
|
416
468
|
val = rb_apply(hash, rb_intern("dig"), array);
|
|
417
|
-
|
|
469
|
+
ALLOCV_END(path_tmp);
|
|
418
470
|
return val;
|
|
419
471
|
}
|
|
420
472
|
|
|
421
|
-
|
|
422
|
-
|
|
473
|
+
val = mmdb_entry_data_decode(&entry_data);
|
|
474
|
+
ALLOCV_END(path_tmp);
|
|
475
|
+
return val;
|
|
423
476
|
}
|
|
424
477
|
|
|
425
478
|
static VALUE
|
|
426
479
|
rb_geoip2_lr_netmask(VALUE self)
|
|
427
480
|
{
|
|
428
|
-
|
|
481
|
+
LookupResult *result = NULL;
|
|
429
482
|
|
|
430
483
|
TypedData_Get_Struct(self,
|
|
431
|
-
|
|
484
|
+
LookupResult,
|
|
432
485
|
&rb_lookup_result_type,
|
|
433
486
|
result);
|
|
434
487
|
|
|
435
|
-
return UINT2NUM(result->netmask);
|
|
488
|
+
return UINT2NUM(result->result.netmask);
|
|
436
489
|
}
|
|
437
490
|
|
|
438
491
|
static VALUE
|
|
439
492
|
rb_geoip2_lr_to_h(VALUE self)
|
|
440
493
|
{
|
|
441
|
-
|
|
494
|
+
LookupResult *result = NULL;
|
|
442
495
|
MMDB_entry_data_list_s *entry_data_list = NULL;
|
|
443
496
|
VALUE hash;
|
|
444
497
|
VALUE cache;
|
|
@@ -452,11 +505,8 @@ rb_geoip2_lr_to_h(VALUE self)
|
|
|
452
505
|
}
|
|
453
506
|
}
|
|
454
507
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
&rb_lookup_result_type,
|
|
458
|
-
result);
|
|
459
|
-
status = MMDB_get_entry_data_list(&result->entry, &entry_data_list);
|
|
508
|
+
result = lookup_result_get_open(self);
|
|
509
|
+
status = MMDB_get_entry_data_list(&result->result.entry, &entry_data_list);
|
|
460
510
|
if (status != MMDB_SUCCESS) {
|
|
461
511
|
rb_raise(rb_eGeoIP2Error, "%s", MMDB_strerror(status));
|
|
462
512
|
}
|
data/lib/geoip2/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: geoip2_c
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- okkez
|
|
@@ -101,6 +101,7 @@ extensions:
|
|
|
101
101
|
- ext/geoip2/extconf.rb
|
|
102
102
|
extra_rdoc_files: []
|
|
103
103
|
files:
|
|
104
|
+
- ".github/dependabot.yml"
|
|
104
105
|
- ".github/workflows/ubuntu.yml"
|
|
105
106
|
- ".github/workflows/windows.yml"
|
|
106
107
|
- ".gitignore"
|
|
@@ -141,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
141
142
|
- !ruby/object:Gem::Version
|
|
142
143
|
version: '0'
|
|
143
144
|
requirements: []
|
|
144
|
-
rubygems_version: 4.0.
|
|
145
|
+
rubygems_version: 4.0.15
|
|
145
146
|
specification_version: 4
|
|
146
147
|
summary: Write a short summary, because Rubygems requires one.
|
|
147
148
|
test_files: []
|