gcc_jit_rvalue_dereference_field has error-checking to ensure that the field is of the correct struct, but it turned out that gcc_jit_lvalue_access_field and gcc_jit_rvalue_access_field were missing this check, and this just bit a user.
Add the missing validation, along with testcases. Takes "make check-jit" from 7974 to 8014 passes. Committed to trunk as r224565. gcc/jit/ChangeLog: * libgccjit.c (gcc_jit_lvalue_access_field): Verify that the field is for the correct struct. (gcc_jit_rvalue_access_field): Likewise. gcc/testsuite/ChangeLog: * jit.dg/test-error-accessing-field-in-other-struct.c: Rename to... * jit.dg/test-error-gcc_jit_rvalue_dereference_field-wrong-struct.c: ...this. * jit.dg/test-error-gcc_jit_lvalue_access_field-wrong-struct.c: New testcase. * jit.dg/test-error-gcc_jit_rvalue_access_field-wrong-struct.c: New testcase. --- gcc/jit/libgccjit.c | 18 ++++ .../test-error-accessing-field-in-other-struct.c | 114 --------------------- ...rror-gcc_jit_lvalue_access_field-wrong-struct.c | 111 ++++++++++++++++++++ ...rror-gcc_jit_rvalue_access_field-wrong-struct.c | 110 ++++++++++++++++++++ ...gcc_jit_rvalue_dereference_field-wrong-struct.c | 114 +++++++++++++++++++++ 5 files changed, 353 insertions(+), 114 deletions(-) delete mode 100644 gcc/testsuite/jit.dg/test-error-accessing-field-in-other-struct.c create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_access_field-wrong-struct.c create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_rvalue_access_field-wrong-struct.c create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_rvalue_dereference_field-wrong-struct.c diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 7eb66bd..dedf942 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -1671,6 +1671,15 @@ gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_, RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc, "field %s has not been placed in a struct", field->get_debug_string ()); + gcc::jit::recording::type *underlying_type = + struct_->get_type (); + RETURN_NULL_IF_FAIL_PRINTF2 ( + (field->get_container ()->unqualified () + == underlying_type->unqualified ()), + struct_->m_ctxt, loc, + "%s is not a field of %s", + field->get_debug_string (), + underlying_type->get_debug_string ()); return (gcc_jit_lvalue *)struct_->access_field (loc, field); } @@ -1694,6 +1703,15 @@ gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_, RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc, "field %s has not been placed in a struct", field->get_debug_string ()); + gcc::jit::recording::type *underlying_type = + struct_->get_type (); + RETURN_NULL_IF_FAIL_PRINTF2 ( + (field->get_container ()->unqualified () + == underlying_type->unqualified ()), + struct_->m_ctxt, loc, + "%s is not a field of %s", + field->get_debug_string (), + underlying_type->get_debug_string ()); return (gcc_jit_rvalue *)struct_->access_field (loc, field); } diff --git a/gcc/testsuite/jit.dg/test-error-accessing-field-in-other-struct.c b/gcc/testsuite/jit.dg/test-error-accessing-field-in-other-struct.c deleted file mode 100644 index f10954b..0000000 --- a/gcc/testsuite/jit.dg/test-error-accessing-field-in-other-struct.c +++ /dev/null @@ -1,114 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> - -#include "libgccjit.h" - -#include "harness.h" - -struct foo -{ - int x; - int y; -}; - -struct bar -{ - int p; - int q; -}; - -void -create_code (gcc_jit_context *ctxt, void *user_data) -{ - /* Let's try to inject the equivalent of: - void - test_bogus_access (struct foo *f) - { - f->p = f->q; - } - i.e. using the wrong struct. - */ - gcc_jit_type *void_type = - gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); - gcc_jit_type *int_type = - gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); - - /* Map "struct foo". */ - gcc_jit_field *x = - gcc_jit_context_new_field (ctxt, - NULL, - int_type, - "x"); - gcc_jit_field *y = - gcc_jit_context_new_field (ctxt, - NULL, - int_type, - "y"); - gcc_jit_field *foo_fields[] = {x, y}; - gcc_jit_struct *struct_foo = - gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, foo_fields); - - /* Map "struct bar". */ - gcc_jit_field *p = - gcc_jit_context_new_field (ctxt, - NULL, - int_type, - "p"); - gcc_jit_field *q = - gcc_jit_context_new_field (ctxt, - NULL, - int_type, - "q"); - /* We don't actually need a gcc_jit_type for "struct bar" for the test. */ - gcc_jit_field *bar_fields[] = {p, q}; - (void)gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, bar_fields); - - gcc_jit_type *foo_ptr = - gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_foo)); - - /* Build the test function. */ - gcc_jit_param *param_f = - gcc_jit_context_new_param (ctxt, NULL, foo_ptr, "f"); - gcc_jit_function *test_fn = - gcc_jit_context_new_function (ctxt, NULL, - GCC_JIT_FUNCTION_EXPORTED, - void_type, - "test_bogus_access", - 1, ¶m_f, - 0); - - /* Erroneous: f->p = ... */ - gcc_jit_lvalue *lvalue = - gcc_jit_rvalue_dereference_field ( - gcc_jit_param_as_rvalue (param_f), - NULL, - p); - - /* Erroneous: ... = f->q; */ - gcc_jit_rvalue *rvalue = - gcc_jit_lvalue_as_rvalue ( - gcc_jit_rvalue_dereference_field ( - gcc_jit_param_as_rvalue (param_f), - NULL, - q)); - - gcc_jit_block *block = - gcc_jit_function_new_block (test_fn, NULL); - gcc_jit_block_add_assignment ( - block, - NULL, - lvalue, rvalue); - gcc_jit_block_end_with_void_return (block, NULL); -} - -void -verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) -{ - CHECK_VALUE (result, NULL); - - /* Verify that the correct error message was emitted. */ - CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), - "gcc_jit_rvalue_dereference_field:" - " p is not a field of struct foo"); -} - diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_access_field-wrong-struct.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_access_field-wrong-struct.c new file mode 100644 index 0000000..b47571e --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_access_field-wrong-struct.c @@ -0,0 +1,111 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit.h" + +#include "harness.h" + +struct foo +{ + int x; + int y; +}; + +struct bar +{ + int p; + int q; +}; + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + void + test_bogus_access (struct foo f) + { + f.p = f.x; + } + i.e. using the wrong struct for the LHS. + */ + gcc_jit_type *void_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + + /* Map "struct foo". */ + gcc_jit_field *x = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "x"); + gcc_jit_field *y = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "y"); + gcc_jit_field *foo_fields[] = {x, y}; + gcc_jit_struct *struct_foo = + gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, foo_fields); + + /* Map "struct bar". */ + gcc_jit_field *p = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "p"); + gcc_jit_field *q = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "q"); + /* We don't actually need a gcc_jit_type for "struct bar" for the test. */ + gcc_jit_field *bar_fields[] = {p, q}; + (void)gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, bar_fields); + + /* Build the test function. */ + gcc_jit_param *param_f = + gcc_jit_context_new_param (ctxt, NULL, + gcc_jit_struct_as_type (struct_foo), "f"); + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "test_bogus_access", + 1, ¶m_f, + 0); + + /* Erroneous: f.p = ... */ + gcc_jit_lvalue *lvalue = + gcc_jit_lvalue_access_field ( + gcc_jit_param_as_lvalue (param_f), + NULL, + p); + + /* OK: ... = f.x; */ + gcc_jit_rvalue *rvalue = + gcc_jit_lvalue_as_rvalue ( + gcc_jit_lvalue_access_field ( + gcc_jit_param_as_lvalue (param_f), + NULL, + x)); + + gcc_jit_block *block = + gcc_jit_function_new_block (test_fn, NULL); + gcc_jit_block_add_assignment ( + block, + NULL, + lvalue, rvalue); + gcc_jit_block_end_with_void_return (block, NULL); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_VALUE (result, NULL); + + /* Verify that the correct error message was emitted. */ + CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), + "gcc_jit_lvalue_access_field:" + " p is not a field of struct foo"); +} diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_rvalue_access_field-wrong-struct.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_rvalue_access_field-wrong-struct.c new file mode 100644 index 0000000..c09acfb --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_rvalue_access_field-wrong-struct.c @@ -0,0 +1,110 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit.h" + +#include "harness.h" + +struct foo +{ + int x; + int y; +}; + +struct bar +{ + int p; + int q; +}; + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + void + test_bogus_access (struct foo f) + { + f.x = f.p; + } + i.e. using the wrong struct for the RHS. + */ + gcc_jit_type *void_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + + /* Map "struct foo". */ + gcc_jit_field *x = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "x"); + gcc_jit_field *y = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "y"); + gcc_jit_field *foo_fields[] = {x, y}; + gcc_jit_struct *struct_foo = + gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, foo_fields); + + /* Map "struct bar". */ + gcc_jit_field *p = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "p"); + gcc_jit_field *q = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "q"); + /* We don't actually need a gcc_jit_type for "struct bar" for the test. */ + gcc_jit_field *bar_fields[] = {p, q}; + (void)gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, bar_fields); + + /* Build the test function. */ + gcc_jit_param *param_f = + gcc_jit_context_new_param (ctxt, NULL, + gcc_jit_struct_as_type (struct_foo), "f"); + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "test_bogus_access", + 1, ¶m_f, + 0); + + /* OK: f.x = ... */ + gcc_jit_lvalue *lvalue = + gcc_jit_lvalue_access_field ( + gcc_jit_param_as_lvalue (param_f), + NULL, + x); + + /* Erroneous: ... = f.p; */ + gcc_jit_rvalue *rvalue = + gcc_jit_rvalue_access_field ( + gcc_jit_param_as_rvalue (param_f), + NULL, + p); + + gcc_jit_block *block = + gcc_jit_function_new_block (test_fn, NULL); + gcc_jit_block_add_assignment ( + block, + NULL, + lvalue, rvalue); + gcc_jit_block_end_with_void_return (block, NULL); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_VALUE (result, NULL); + + /* Verify that the correct error message was emitted. */ + CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), + "gcc_jit_rvalue_access_field:" + " p is not a field of struct foo"); +} diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_rvalue_dereference_field-wrong-struct.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_rvalue_dereference_field-wrong-struct.c new file mode 100644 index 0000000..f10954b --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_rvalue_dereference_field-wrong-struct.c @@ -0,0 +1,114 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit.h" + +#include "harness.h" + +struct foo +{ + int x; + int y; +}; + +struct bar +{ + int p; + int q; +}; + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + void + test_bogus_access (struct foo *f) + { + f->p = f->q; + } + i.e. using the wrong struct. + */ + gcc_jit_type *void_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + + /* Map "struct foo". */ + gcc_jit_field *x = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "x"); + gcc_jit_field *y = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "y"); + gcc_jit_field *foo_fields[] = {x, y}; + gcc_jit_struct *struct_foo = + gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, foo_fields); + + /* Map "struct bar". */ + gcc_jit_field *p = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "p"); + gcc_jit_field *q = + gcc_jit_context_new_field (ctxt, + NULL, + int_type, + "q"); + /* We don't actually need a gcc_jit_type for "struct bar" for the test. */ + gcc_jit_field *bar_fields[] = {p, q}; + (void)gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, bar_fields); + + gcc_jit_type *foo_ptr = + gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_foo)); + + /* Build the test function. */ + gcc_jit_param *param_f = + gcc_jit_context_new_param (ctxt, NULL, foo_ptr, "f"); + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "test_bogus_access", + 1, ¶m_f, + 0); + + /* Erroneous: f->p = ... */ + gcc_jit_lvalue *lvalue = + gcc_jit_rvalue_dereference_field ( + gcc_jit_param_as_rvalue (param_f), + NULL, + p); + + /* Erroneous: ... = f->q; */ + gcc_jit_rvalue *rvalue = + gcc_jit_lvalue_as_rvalue ( + gcc_jit_rvalue_dereference_field ( + gcc_jit_param_as_rvalue (param_f), + NULL, + q)); + + gcc_jit_block *block = + gcc_jit_function_new_block (test_fn, NULL); + gcc_jit_block_add_assignment ( + block, + NULL, + lvalue, rvalue); + gcc_jit_block_end_with_void_return (block, NULL); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_VALUE (result, NULL); + + /* Verify that the correct error message was emitted. */ + CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), + "gcc_jit_rvalue_dereference_field:" + " p is not a field of struct foo"); +} + -- 1.8.5.3