Bug 47346 - access control for nested type is ignored in class template
Summary: access control for nested type is ignored in class template
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: 11.0
Assignee: Patrick Palka
URL:
Keywords: accepts-invalid
: 49388 50097 51584 58896 59081 59191 61816 (view as bug list)
Depends on:
Blocks: 59002
  Show dependency treegraph
 
Reported: 2011-01-18 15:15 UTC by Jonathan Wakely
Modified: 2020-07-04 04:40 UTC (History)
14 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-03-12 00:00:00


Attachments
Work in progress patch (5.17 KB, patch)
2011-08-11 18:52 UTC, Dodji Seketeli
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2011-01-18 15:15:18 UTC
There are several bugs about failure to do access checking for template parameters and in function templates (PR 40901, PR 41437, PR 45011, PR 45917) but I don't think this is a dup of any of them

class C
{
  struct Private { };
};

template<typename T>
struct exploit1
{
    typedef C::Private type;
};

exploit1<int>::type x1;   // error

// similarly for base-specifier
template<typename T>
struct exploit2 : C::Private
{
};

exploit2<int> x2;   // error
Comment 1 Jonathan Wakely 2011-06-13 09:10:59 UTC
*** Bug 49388 has been marked as a duplicate of this bug. ***
Comment 2 Dodji Seketeli 2011-08-11 18:41:53 UTC
Another variation of the same theme is:

class C
{
    struct Private { };
};

template<typename T>
struct exploit3
{
    template<class U = C::Private>
    struct E {};
};

void
bar()
{
    exploit3<int>::E<> e;
}
Comment 3 Dodji Seketeli 2011-08-11 18:52:54 UTC
Created attachment 24985 [details]
Work in progress patch

I am currently testing this patch.

The problem I see is twofold.

First, the infrastructure I added a while back to do access checking of references to types, at template instantiation time,  was limited to typedefs.

This bug seems to suggest that the access checking should be done for references to all types.  Not just typedefs.

Second, add_typedef_to_current_template_for_access_check assumes that a "current template" is present.  When we are parsing the class header (for e.g the base clause) or the template parameter list, the "current template" is not present yet.  In that case, a possible solution is the stash away, for some short while, the types access that is to be checked, until the current template becomes available.

This is the approach taken by this patch.
Comment 4 Dodji Seketeli 2011-08-17 15:26:01 UTC
Candidate fix posted to http://gcc.gnu.org/ml/gcc-patches/2011-08/msg01404.html
Comment 5 Paolo Carlini 2011-09-29 02:20:34 UTC
Out of curiosity, does the posted patch fix at once *all* the issues mentioned in the Description? It would be great to have it!
Comment 6 dodji@seketeli.org 2011-09-30 10:26:29 UTC
"paolo.carlini at oracle dot com" <gcc-bugzilla@gcc.gnu.org> a écrit:

> Out of curiosity, does the posted patch fix at once *all* the issues mentioned
> in the Description?

Yes it does, AFAICT.

> It would be great to have it!

I am onto something else at the moment, but I intend to address Jason's
comment to the patch I posted when I am done.  Sorry for the delay.
Comment 7 Paolo Carlini 2011-09-30 10:33:15 UTC
Great. By the way, I think I didn't see any comment, that's why I asked ;)
Comment 8 dodji@seketeli.org 2011-09-30 11:41:14 UTC
The comment was posted in another month:

http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00536.html

Another hint at why we need  a better patch/comments tracker :)
Comment 9 Paolo Carlini 2011-10-18 11:31:06 UTC
*** Bug 50097 has been marked as a duplicate of this bug. ***
Comment 10 Jason Merrill 2013-03-27 13:28:24 UTC
Even simpler:

class B { struct C {}; };
template <class T> struct A { B::C c; };
A<int> a;
Comment 11 Paolo Carlini 2013-07-06 23:42:39 UTC
Dodji, any news? ;)
Comment 12 Jonathan Wakely 2013-11-12 01:07:25 UTC
*** Bug 59081 has been marked as a duplicate of this bug. ***
Comment 13 Paolo Carlini 2013-11-19 16:28:10 UTC
*** Bug 59191 has been marked as a duplicate of this bug. ***
Comment 14 Andrew Pinski 2014-07-16 06:11:38 UTC
*** Bug 61816 has been marked as a duplicate of this bug. ***
Comment 15 Andrew Schepler 2017-10-16 03:09:46 UTC
Bug 58896 looks closely related. Would it be changed by the proposed patch? Should it be made a duplicate?
Comment 16 Jonathan Wakely 2017-10-16 10:23:11 UTC
*** Bug 58896 has been marked as a duplicate of this bug. ***
Comment 17 Jonathan Wakely 2019-01-24 09:44:57 UTC
*** Bug 51584 has been marked as a duplicate of this bug. ***
Comment 18 CVS Commits 2020-06-16 12:59:49 UTC
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:92bed036098928cd4659c8990e14cf7ad040e0c2

commit r11-1350-g92bed036098928cd4659c8990e14cf7ad040e0c2
Author: Patrick Palka <ppalka@redhat.com>
Date:   Tue Jun 16 08:21:33 2020 -0400

    c++: Improve access checking inside templates [PR41437]
    
    This patch generalizes our existing functionality for deferring access
    checking of typedefs when parsing a function or class template to now
    defer all kinds of access checks until template instantiation time,
    including member function and member object accesses.
    
    Since all access checks eventually go through enforce_access, the main
    component of this patch is new handling inside enforce_access to defer
    the current access check if we're inside a template.  The bulk of the
    rest of the patch consists of removing now-unneeded code pertaining to
    suppressing access checks inside templates or pertaining to
    typedef-specific access handling.  Renamings and other changes with no
    functional impact have been split off into the followup patch.
    
    gcc/cp/ChangeLog:
    
            PR c++/41437
            PR c++/47346
            * call.c (enforce_access): Move to semantics.c.
            * cp-tree.h (enforce_access): Delete.
            (get_types_needing_access_check): Delete.
            (add_typedef_to_current_template_for_access_check): Delete.
            * decl.c (make_typename_type): Adjust accordingly.  Use
            check_accessibility_of_qualified_id instead of directly using
            perform_or_defer_access_check.
            * parser.c (cp_parser_template_declaration_after_parameters):
            Don't push a dk_no_check access state when parsing a template.
            * pt.c (get_types_needing_access_check): Delete.
            (append_type_to_template_for_access_check_1): Delete.
            (perform_typedefs_access_check): Adjust.  If type_decl is a
            FIELD_DECL, also check its DECL_CONTEXT for dependence. Use
            tsubst_copy instead of tsubst to substitute into type_decl so
            that we substitute into the DECL_CONTEXT of a FIELD_DECL.
            (append_type_to_template_for_access_check): Delete.
            * search.c (accessible_p): Remove the processing_template_decl
            early exit.
            * semantics.c (enforce_access): Moved from call.c.  If we're
            parsing a template and the access check failed, add the check to
            TI_TYPEDEFS_NEEDING_ACCESS_CHECKING.
            (perform_or_defer_access_check): Adjust comment.
            (add_typedef_to_current_template_for_access_check): Delete.
            (check_accessibility_of_qualified_id):  Adjust accordingly.
            Exit early if the scope is dependent.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/41437
            PR c++/47346
            * g++.dg/cpp2a/concepts-using2.C: Adjust.
            * g++.dg/lto/20081219_1.C: Adjust.
            * g++.dg/lto/20091002-1_0.C: Adjust.
            * g++.dg/lto/pr65475c_0.C: Adjust.
            * g++.dg/opt/dump1.C: Adjust.
            * g++.dg/other/pr53574.C: Adjust.
            * g++.dg/template/access30.C: New test.
            * g++.dg/template/access31.C: New test.
            * g++.dg/wrappers/wrapper-around-type-pack-expansion.C: Adjust.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/94003
            * testsuite/20_util/is_constructible/94003.cc: New test.
Comment 19 CVS Commits 2020-06-16 12:59:55 UTC
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:668ef28fbb44c1e51d9c5a35b421903c98d87b03

commit r11-1351-g668ef28fbb44c1e51d9c5a35b421903c98d87b03
Author: Patrick Palka <ppalka@redhat.com>
Date:   Tue Jun 16 08:21:36 2020 -0400

    c++: Clean up previous change [PR41437]
    
    The previous patch mostly avoided making any changes that had no
    functional impact, such as adjusting now-outdated comments and
    performing renamings.  Such changes have been consolidated to this
    followup patch for easier review.
    
    The main change here is that we now reuse struct deferred_access_check
    as the element type of the vector TI_TYPEDEFS_NEEDING_ACCESS_CHECKING
    (now renamed to TI_DEFERRED_ACCESS_CHECKS, since it may contain any kind
    of access check).
    
    gcc/cp/ChangeLog:
    
            PR c++/41437
            PR c++/47346
            * cp-tree.h (qualified_typedef_usage_s): Delete.
            (qualified_typedef_usage_t): Delete.
            (deferred_access_check): Move up in file.
            (tree_template_info::typedefs_needing_access_checking): Delete.
            (tree_template_info::deferred_access_checks): New field.
            (TI_TYPEDEFS_NEEDING_ACCESS_CHECKING): Rename to ...
            (TI_DEFERRED_ACCESS_CHECKS): ... this, and adjust accordingly.
            * pt.c (perform_typedefs_access_check): Rename to ...
            (perform_instantiation_time_access_checks): ... this, and adjust
            accordingly.  Remove unnecessary tree tests.
            (instantiate_class_template_1): Adjust accordingly.
            (instantiate_decl): Likewise.
            * semantics.c (enforce_access): Likewise.
Comment 20 Patrick Palka 2020-06-16 13:02:28 UTC
Fixed for GCC 11.