Skip to content

Commit 49bd976

Browse files
authored
Merge pull request #999 from carlosmn/cmn/strarray-dispose
Use a more explicit way of correctly disposing `git_strarray` when we're using ruby strings
2 parents 481b46d + 7e43ef5 commit 49bd976

8 files changed

Lines changed: 55 additions & 33 deletions

File tree

ext/rugged/rugged.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,14 +448,23 @@ void rugged_rb_ary_to_strarray(VALUE rb_array, git_strarray *str_array)
448448
Check_Type(rb_ary_entry(rb_array, i), T_STRING);
449449

450450
str_array->count = RARRAY_LEN(rb_array);
451-
str_array->strings = xmalloc(str_array->count * sizeof(char *));
451+
str_array->strings = xcalloc(str_array->count, sizeof(char *));
452452

453453
for (i = 0; i < RARRAY_LEN(rb_array); ++i) {
454454
VALUE rb_string = rb_ary_entry(rb_array, i);
455455
str_array->strings[i] = StringValueCStr(rb_string);
456456
}
457457
}
458458

459+
void rugged_strarray_dispose(git_strarray *str_array)
460+
{
461+
/* We only free this one pointer as the strings inside are owned by ruby */
462+
xfree(str_array->strings);
463+
464+
str_array->strings = NULL;
465+
str_array->count = 0;
466+
}
467+
459468
void rugged_parse_merge_file_options(git_merge_file_options *opts, VALUE rb_options)
460469
{
461470
VALUE rb_value;

ext/rugged/rugged.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,27 @@ const char * rugged_refname_from_string_or_ref(VALUE rb_name_or_ref);
101101

102102
VALUE rugged_signature_from_buffer(const char *buffer, const char *encoding_name);
103103

104+
/**
105+
* Convert the given array of strings to a git_strarray referencing the ruby C strings
106+
*
107+
* The git_strarray must be allocated somewhere (typically it's in the stack)
108+
* and this function will allocate an array of strings and set all the values to
109+
* the ruby-owned C string pointer for the corresponding ruby string.
110+
*
111+
* The pointer in the strings field is owend by us, the memory it points to is
112+
* owned by ruby.
113+
*/
104114
void rugged_rb_ary_to_strarray(VALUE rb_array, git_strarray *str_array);
115+
116+
/**
117+
* Free a git_strarray allocated by rugged_rb_ary_to_strarray
118+
*
119+
* This is different from git_strarray_dispose because we use pointers into the
120+
* ruby C strings and don't own the strings. On top of that the allocators could
121+
* be different (though we set it to be the same one at the moment).
122+
*/
123+
void rugged_strarray_dispose(git_strarray *str_array);
124+
105125
VALUE rugged_strarray_to_rb_ary(git_strarray *str_array);
106126

107127
#define CALLABLE_OR_RAISE(ret, name) \

ext/rugged/rugged_commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ static VALUE rb_git_commit_to_mbox(int argc, VALUE *argv, VALUE self)
651651

652652
cleanup:
653653

654-
xfree(opts.pathspec.strings);
654+
rugged_strarray_dispose(&opts.pathspec);
655655
git_buf_dispose(&email_patch);
656656
rugged_exception_check(error);
657657

ext/rugged/rugged_diff.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,19 +138,12 @@ void rugged_parse_diff_options(git_diff_options *opts, VALUE rb_options)
138138

139139
rb_value = rb_hash_aref(rb_options, CSTR2SYM("paths"));
140140
if (!NIL_P(rb_value)) {
141-
int i;
141+
/*
142+
* rugged_rb_ary_to_strarray allows single values and we
143+
* want to be more specific here
144+
*/
142145
Check_Type(rb_value, T_ARRAY);
143-
144-
for (i = 0; i < RARRAY_LEN(rb_value); ++i)
145-
Check_Type(rb_ary_entry(rb_value, i), T_STRING);
146-
147-
opts->pathspec.count = RARRAY_LEN(rb_value);
148-
opts->pathspec.strings = xmalloc(opts->pathspec.count * sizeof(char *));
149-
150-
for (i = 0; i < RARRAY_LEN(rb_value); ++i) {
151-
VALUE rb_path = rb_ary_entry(rb_value, i);
152-
opts->pathspec.strings[i] = StringValueCStr(rb_path);
153-
}
146+
rugged_rb_ary_to_strarray(rb_value, &opts->pathspec);
154147
}
155148

156149
rb_value = rb_hash_aref(rb_options, CSTR2SYM("context_lines"));

ext/rugged/rugged_index.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ static VALUE rb_git_index_add_all(int argc, VALUE *argv, VALUE self)
408408
error = git_index_add_all(index, &pathspecs, flags,
409409
rb_block_given_p() ? rugged__index_matched_path_cb : NULL, &exception);
410410

411-
xfree(pathspecs.strings);
411+
rugged_strarray_dispose(&pathspecs);
412412

413413
if (exception)
414414
rb_jump_tag(exception);
@@ -458,7 +458,7 @@ static VALUE rb_git_index_update_all(int argc, VALUE *argv, VALUE self)
458458
error = git_index_update_all(index, &pathspecs,
459459
rb_block_given_p() ? rugged__index_matched_path_cb : NULL, &exception);
460460

461-
xfree(pathspecs.strings);
461+
rugged_strarray_dispose(&pathspecs);
462462

463463
if (exception)
464464
rb_jump_tag(exception);
@@ -504,7 +504,7 @@ static VALUE rb_git_index_remove_all(int argc, VALUE *argv, VALUE self)
504504
error = git_index_remove_all(index, &pathspecs,
505505
rb_block_given_p() ? rugged__index_matched_path_cb : NULL, &exception);
506506

507-
xfree(pathspecs.strings);
507+
rugged_strarray_dispose(&pathspecs);
508508

509509
if (exception)
510510
rb_jump_tag(exception);
@@ -705,7 +705,7 @@ static VALUE rb_git_diff_tree_to_index(VALUE self, VALUE rb_other, VALUE rb_opti
705705
TypedData_Get_Struct(rb_other, git_tree, &rugged_object_type, other_tree);
706706
error = git_diff_tree_to_index(&diff, repo, other_tree, index, &opts);
707707

708-
xfree(opts.pathspec.strings);
708+
rugged_strarray_dispose(&opts.pathspec);
709709
rugged_exception_check(error);
710710

711711
return rugged_diff_new(rb_cRuggedDiff, owner, diff);
@@ -728,7 +728,7 @@ static VALUE rb_git_diff_index_to_workdir(VALUE self, VALUE rb_options)
728728

729729
error = git_diff_index_to_workdir(&diff, repo, index, &opts);
730730

731-
xfree(opts.pathspec.strings);
731+
rugged_strarray_dispose(&opts.pathspec);
732732
rugged_exception_check(error);
733733

734734
return rugged_diff_new(rb_cRuggedDiff, owner, diff);

ext/rugged/rugged_remote.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ static VALUE rb_git_remote_ls(int argc, VALUE *argv, VALUE self)
354354
cleanup:
355355

356356
git_remote_disconnect(remote);
357-
xfree(custom_headers.strings);
357+
rugged_strarray_dispose(&custom_headers);
358358

359359
if (payload.exception)
360360
rb_jump_tag(payload.exception);
@@ -527,7 +527,7 @@ static VALUE rb_git_remote_check_connection(int argc, VALUE *argv, VALUE self)
527527
git_remote *remote;
528528
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
529529
git_proxy_options proxy_options = GIT_PROXY_OPTIONS_INIT;
530-
git_strarray custom_headers = {0};
530+
git_strarray custom_headers = { NULL, 0 };
531531
struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, 0 };
532532
VALUE rb_direction, rb_options;
533533
ID id_direction;
@@ -552,7 +552,7 @@ static VALUE rb_git_remote_check_connection(int argc, VALUE *argv, VALUE self)
552552
error = git_remote_connect(remote, direction, &callbacks, &proxy_options, &custom_headers);
553553
git_remote_disconnect(remote);
554554

555-
xfree(custom_headers.strings);
555+
rugged_strarray_dispose(&custom_headers);
556556

557557
if (payload.exception)
558558
rb_jump_tag(payload.exception);
@@ -655,8 +655,8 @@ static VALUE rb_git_remote_fetch(int argc, VALUE *argv, VALUE self)
655655

656656
error = git_remote_fetch(remote, &refspecs, &opts, log_message);
657657

658-
xfree(refspecs.strings);
659-
xfree(opts.custom_headers.strings);
658+
rugged_strarray_dispose(&refspecs);
659+
rugged_strarray_dispose(&opts.custom_headers);
660660

661661
if (payload.exception)
662662
rb_jump_tag(payload.exception);
@@ -740,8 +740,8 @@ static VALUE rb_git_remote_push(int argc, VALUE *argv, VALUE self)
740740

741741
error = git_remote_push(remote, &refspecs, &opts);
742742

743-
xfree(refspecs.strings);
744-
xfree(opts.custom_headers.strings);
743+
rugged_strarray_dispose(&refspecs);
744+
rugged_strarray_dispose(&opts.custom_headers);
745745

746746
if (payload.exception)
747747
rb_jump_tag(payload.exception);

ext/rugged/rugged_repo.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,7 +1893,7 @@ static VALUE rb_git_repo_reset_path(int argc, VALUE *argv, VALUE self)
18931893

18941894
error = git_reset_default(repo, target, &pathspecs);
18951895

1896-
xfree(pathspecs.strings);
1896+
rugged_strarray_dispose(&pathspecs);
18971897
git_object_free(target);
18981898

18991899
rugged_exception_check(error);
@@ -2391,7 +2391,7 @@ static VALUE rb_git_checkout_tree(int argc, VALUE *argv, VALUE self)
23912391
rugged_parse_checkout_options(&opts, rb_options);
23922392

23932393
error = git_checkout_tree(repo, treeish, &opts);
2394-
xfree(opts.paths.strings);
2394+
rugged_strarray_dispose(&opts.paths);
23952395

23962396
if ((payload = opts.notify_payload) != NULL) {
23972397
exception = payload->exception;
@@ -2439,7 +2439,7 @@ static VALUE rb_git_checkout_index(int argc, VALUE *argv, VALUE self)
24392439
rugged_parse_checkout_options(&opts, rb_options);
24402440

24412441
error = git_checkout_index(repo, index, &opts);
2442-
xfree(opts.paths.strings);
2442+
rugged_strarray_dispose(&opts.paths);
24432443

24442444
if ((payload = opts.notify_payload) != NULL) {
24452445
exception = payload->exception;
@@ -2482,7 +2482,7 @@ static VALUE rb_git_checkout_head(int argc, VALUE *argv, VALUE self)
24822482
rugged_parse_checkout_options(&opts, rb_options);
24832483

24842484
error = git_checkout_head(repo, &opts);
2485-
xfree(opts.paths.strings);
2485+
rugged_strarray_dispose(&opts.paths);
24862486

24872487
if ((payload = opts.notify_payload) != NULL) {
24882488
exception = payload->exception;

ext/rugged/rugged_tree.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ static VALUE rb_git_diff_tree_to_index(VALUE self, VALUE rb_repo, VALUE rb_self,
381381

382382
error = git_diff_tree_to_index(&diff, repo, tree, index, &opts);
383383

384-
xfree(opts.pathspec.strings);
384+
rugged_strarray_dispose(&opts.pathspec);
385385
rugged_exception_check(error);
386386

387387
return rugged_diff_new(rb_cRuggedDiff, rb_repo, diff);
@@ -430,7 +430,7 @@ static VALUE rb_git_diff_tree_to_tree(VALUE self, VALUE rb_repo, VALUE rb_tree,
430430

431431
diff = rb_thread_call_without_gvl(rb_git_diff_tree_to_tree_nogvl, &args, RUBY_UBF_PROCESS, NULL);
432432

433-
xfree(opts.pathspec.strings);
433+
rugged_strarray_dispose(&opts.pathspec);
434434
rugged_exception_check(args.error);
435435

436436
return rugged_diff_new(rb_cRuggedDiff, rb_repo, diff);
@@ -465,7 +465,7 @@ static VALUE rb_git_tree_diff_workdir(int argc, VALUE *argv, VALUE self)
465465

466466
error = git_diff_tree_to_workdir(&diff, repo, tree, &opts);
467467

468-
xfree(opts.pathspec.strings);
468+
rugged_strarray_dispose(&opts.pathspec);
469469
rugged_exception_check(error);
470470

471471
return rugged_diff_new(rb_cRuggedDiff, owner, diff);

0 commit comments

Comments
 (0)