Skip to content

Don't crash if NULL is passed to mrb_close#2951

Merged
matz merged 1 commit intomruby:masterfrom
tatsuhiro-t:mrb_close_with_nullptr
Sep 14, 2015
Merged

Don't crash if NULL is passed to mrb_close#2951
matz merged 1 commit intomruby:masterfrom
tatsuhiro-t:mrb_close_with_nullptr

Conversation

@tatsuhiro-t
Copy link
Copy Markdown
Contributor

Sometimes it is very useful just return from mrb_close if NULL is
passed as mrb. This is the same spirit of free(3), which just does
nothing if NULL is passed.

Sometimes it is very useful just return from mrb_close if NULL is
passed as mrb.  This is the same spirit of free(3), which just does
nothing if NULL is passed.
@franckverrot
Copy link
Copy Markdown
Contributor

Should we change the semantics of mrb_close in order to return meaningful details about what happened there? Or would it be at a minimum OK to have it warn on stderr that NULL was passed?

@cremno
Copy link
Copy Markdown
Contributor

cremno commented Sep 12, 2015

This is the same spirit of free(3), which just does nothing if NULL is passed.

I'm not opposing merging this but note that isn't true for fclose() or lua_close() since NULL isn't a valid pointer to FILE or lua_State.

@franckverrot: Why?

@franckverrot
Copy link
Copy Markdown
Contributor

@cremno Thinking in terms of side-effects, free either fails, frees memory or doesn't do anything, and as an observer (from the call-site) there's no way to determine what happened (unless you checked for NULL at some point, but calling free could have been avoided in that case).

I think it's a good thing to avoid crashes when we call mrb_close(NULL), but I personally don't like the idea of mixing the “closes the context” and ”does nothing” side-effects.

@matz
Copy link
Copy Markdown
Member

matz commented Sep 13, 2015

do you have any use-case in mind? mrb_close(NULL) is a bug, isn't it?

@tatsuhiro-t
Copy link
Copy Markdown
Contributor Author

My usecase is that when mrb_state is a data field of C++ struct and it could be NULL, then we don't have check whether it is NULL in destructor:

struct Foo {
  Foo(...) : state(nullptr) {
    if (some_condition_met()) {
      state = mrb_open();
    }
  }

  ~Foo() {
    mrb_close(mrb);
  }

  mrb_state *state;
};

As commented earlier, many library functions, like fclose or SSL_free from OpenSSL, will crash if NULL is passed. In those functions, we have to check the argument is NULL or not. Many programs will do this for safety. If it is done in mrb_close, we can save those lines of code.
I always allow passing NULL to these "free" functions when I design this kind of function.

@tsahara tsahara mentioned this pull request Sep 14, 2015
36 tasks
@murasesyuka
Copy link
Copy Markdown
Contributor

👍 I think RAII is good Idiom. and want to Error output.

it warn on stderr that NULL was passed?

@tatsuhiro-t typo? s/mrb_close(mrb);/mrb_close(state)/g

@matz
Copy link
Copy Markdown
Member

matz commented Sep 14, 2015

OK, adding 1 line would not harm.

matz added a commit that referenced this pull request Sep 14, 2015
Don't crash if NULL is passed to mrb_close
@matz matz merged commit e91b7d6 into mruby:master Sep 14, 2015
@franckverrot
Copy link
Copy Markdown
Contributor

@matz Isn't a good case to use mrb_assert instead?

If not, would you be OK to change the semantics of mrb_close to return:

  1. a success value if the whole function ran;
  2. a warning/error value if we returned early due to the precondition of having mrb != NULL not fulfilled?

It'd be the best of both worlds: don't check what you pass to mrb_close if you don't want to, but still provide a way to know what happened there with the value it returns.

@cremno
Copy link
Copy Markdown
Contributor

cremno commented Sep 15, 2015

Either mrb_close() accepts a null pointer as argument and immediately returns (this merged PR) or it doesn't (before the merge but mrb_assert() would've been an improvement!).

Everything else would just be complicated. Simply check before the call if that info is needed for some reason.

@mattn
Copy link
Copy Markdown
Contributor

mattn commented Sep 16, 2015

I'm thinking mrb_close should not be calm for NULL. As you said, free(NULL) is, but fclose(NULL) is not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants