Skip to content

Commit b2e2f80

Browse files
committed
Merge pull request #4558 from 9rnsr/fix5770
Issue 5770 - Template constructor bypass access check
2 parents 714d1b3 + 4cd6985 commit b2e2f80

10 files changed

Lines changed: 426 additions & 337 deletions

File tree

src/access.c

Lines changed: 33 additions & 307 deletions
Original file line numberDiff line numberDiff line change
@@ -15,246 +15,47 @@
1515
#include "root.h"
1616
#include "rmem.h"
1717

18-
#include "enum.h"
19-
#include "aggregate.h"
20-
#include "init.h"
21-
#include "attrib.h"
22-
#include "scope.h"
23-
#include "id.h"
24-
#include "mtype.h"
25-
#include "declaration.h"
2618
#include "aggregate.h"
2719
#include "expression.h"
2820
#include "module.h"
21+
#include "scope.h"
2922

3023
#define LOG 0
3124

32-
/* Code to do access checks
33-
*/
34-
35-
bool hasPackageAccess(Scope *sc, Dsymbol *s);
36-
bool hasPrivateAccess(AggregateDeclaration *ad, Dsymbol *smember);
37-
bool isFriendOf(AggregateDeclaration *ad, AggregateDeclaration *cd);
38-
3925
/****************************************
40-
* Return Prot access for Dsymbol smember in this declaration.
26+
* Check that s is a member of ad (or one of its base casses if exist).
4127
*/
42-
Prot getAccess(AggregateDeclaration *ad, Dsymbol *smember)
28+
bool isMember(AggregateDeclaration *ad, Dsymbol *s)
4329
{
44-
Prot access_ret = Prot(PROTnone);
45-
46-
#if LOG
47-
printf("+AggregateDeclaration::getAccess(this = '%s', smember = '%s')\n",
48-
ad->toChars(), smember->toChars());
49-
#endif
30+
if (s->toParent2() == ad)
31+
return true;
5032

51-
assert(ad->isStructDeclaration() || ad->isClassDeclaration());
52-
if (smember->toParent() == ad)
53-
{
54-
access_ret = smember->prot();
55-
}
56-
else if (smember->isDeclaration()->isStatic())
57-
{
58-
access_ret = smember->prot();
59-
}
6033
if (ClassDeclaration *cd = ad->isClassDeclaration())
6134
{
6235
for (size_t i = 0; i < cd->baseclasses->dim; i++)
6336
{
6437
BaseClass *b = (*cd->baseclasses)[i];
65-
66-
Prot access = getAccess(b->base, smember);
67-
switch (access.kind)
68-
{
69-
case PROTnone:
70-
break;
71-
72-
case PROTprivate:
73-
access_ret = Prot(PROTnone); // private members of base class not accessible
74-
break;
75-
76-
case PROTpackage:
77-
case PROTprotected:
78-
case PROTpublic:
79-
case PROTexport:
80-
// If access is to be tightened
81-
if (b->protection.isMoreRestrictiveThan(access))
82-
access = b->protection;
83-
84-
// Pick path with loosest access
85-
if (access_ret.isMoreRestrictiveThan(access))
86-
access_ret = access;
87-
break;
88-
89-
default:
90-
assert(0);
91-
}
92-
}
93-
}
94-
95-
#if LOG
96-
printf("-AggregateDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
97-
ad->toChars(), smember->toChars(), access_ret);
98-
#endif
99-
return access_ret;
100-
}
101-
102-
/********************************************************
103-
* Helper function for checkAccess()
104-
* Returns:
105-
* false is not accessible
106-
* true is accessible
107-
*/
108-
static bool isAccessible(
109-
Dsymbol *smember,
110-
Dsymbol *sfunc,
111-
AggregateDeclaration *dthis,
112-
AggregateDeclaration *cdscope)
113-
{
114-
assert(dthis);
115-
116-
#if 0
117-
printf("isAccessible for %s.%s in function %s() in scope %s\n",
118-
dthis->toChars(), smember->toChars(),
119-
sfunc ? sfunc->toChars() : "NULL",
120-
cdscope ? cdscope->toChars() : "NULL");
121-
#endif
122-
if (hasPrivateAccess(dthis, sfunc) ||
123-
isFriendOf(dthis, cdscope))
124-
{
125-
if (smember->toParent() == dthis)
126-
return true;
127-
128-
if (ClassDeclaration *cdthis = dthis->isClassDeclaration())
129-
{
130-
for (size_t i = 0; i < cdthis->baseclasses->dim; i++)
131-
{
132-
BaseClass *b = (*cdthis->baseclasses)[i];
133-
Prot access = getAccess(b->base, smember);
134-
if (access.kind >= PROTprotected ||
135-
isAccessible(smember, sfunc, b->base, cdscope))
136-
{
137-
return true;
138-
}
139-
}
140-
}
141-
}
142-
else
143-
{
144-
if (smember->toParent() != dthis)
145-
{
146-
if (ClassDeclaration *cdthis = dthis->isClassDeclaration())
147-
{
148-
for (size_t i = 0; i < cdthis->baseclasses->dim; i++)
149-
{
150-
BaseClass *b = (*cdthis->baseclasses)[i];
151-
if (isAccessible(smember, sfunc, b->base, cdscope))
152-
return true;
153-
}
154-
}
38+
if (isMember(b->base, s))
39+
return true;
15540
}
15641
}
15742
return false;
15843
}
15944

160-
/*******************************
161-
* Do access check for member of this class, this class being the
162-
* type of the 'this' pointer used to access smember.
163-
* Returns true if the member is not accessible.
164-
*/
165-
bool checkAccess(AggregateDeclaration *ad, Loc loc, Scope *sc, Dsymbol *smember)
166-
{
167-
FuncDeclaration *f = sc->func;
168-
AggregateDeclaration *cdscope = sc->getStructClassScope();
169-
170-
#if LOG
171-
printf("AggregateDeclaration::checkAccess() for %s.%s in function %s() in scope %s\n",
172-
ad->toChars(), smember->toChars(),
173-
f ? f->toChars() : NULL,
174-
cdscope ? cdscope->toChars() : NULL);
175-
#endif
176-
177-
Dsymbol *smemberparent = smember->toParent();
178-
if (!smemberparent || !smemberparent->isAggregateDeclaration())
179-
{
180-
#if LOG
181-
printf("not an aggregate member\n");
182-
#endif
183-
return false; // then it is accessible
184-
}
185-
186-
// BUG: should enable this check
187-
//assert(smember->parent->isBaseOf(this, NULL));
188-
189-
bool result;
190-
Prot access;
191-
if (smemberparent == ad)
192-
{
193-
access = smember->prot();
194-
result = access.kind >= PROTpublic ||
195-
hasPrivateAccess(ad, f) ||
196-
isFriendOf(ad, cdscope) ||
197-
(access.kind == PROTpackage && hasPackageAccess(sc, smember)) ||
198-
ad->getAccessModule() == sc->module;
199-
#if LOG
200-
printf("result1 = %d\n", result);
201-
#endif
202-
}
203-
else if ((access = getAccess(ad, smember)).kind >= PROTpublic)
204-
{
205-
result = true;
206-
#if LOG
207-
printf("result2 = %d\n", result);
208-
#endif
209-
}
210-
else if (access.kind == PROTpackage && hasPackageAccess(sc, ad))
211-
{
212-
result = true;
213-
#if LOG
214-
printf("result3 = %d\n", result);
215-
#endif
216-
}
217-
else
218-
{
219-
result = isAccessible(smember, f, ad, cdscope);
220-
#if LOG
221-
printf("result4 = %d\n", result);
222-
#endif
223-
}
224-
if (!result)
225-
{
226-
ad->error(loc, "member %s is not accessible", smember->toChars());
227-
//printf("smember = %s %s, prot = %d, semanticRun = %d\n",
228-
// smember->kind(), smember->toPrettyChars(), smember->prot(), smember->semanticRun);
229-
return true;
230-
}
231-
return false;
232-
}
233-
23445
/****************************************
235-
* Determine if this is the same or friend of cd.
46+
* Determine if scope sc has protection access to s.
23647
*/
237-
bool isFriendOf(AggregateDeclaration *ad, AggregateDeclaration *cd)
48+
bool hasProtectedAccess(Scope *sc, Dsymbol *s)
23849
{
239-
#if LOG
240-
printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", ad->toChars(), cd ? cd->toChars() : "null");
241-
#endif
242-
if (ad == cd)
243-
return true;
244-
245-
// Friends if both are in the same module
246-
//if (toParent() == cd->toParent())
247-
if (cd && ad->getAccessModule() == cd->getAccessModule())
50+
for (Scope *scx = sc; scx; scx = scx->enclosing)
24851
{
249-
#if LOG
250-
printf("\tin same module\n");
251-
#endif
252-
return true;
253-
}
52+
if (!scx->scopesym)
53+
continue;
25454

255-
#if LOG
256-
printf("\tnot friend\n");
257-
#endif
55+
AggregateDeclaration *ad = scx->scopesym->isClassDeclaration();
56+
if (ad && isMember(ad, s))
57+
return true;
58+
}
25859
return false;
25960
}
26061

@@ -335,61 +136,6 @@ bool hasPackageAccess(Scope *sc, Dsymbol *s)
335136
return false;
336137
}
337138

338-
/**********************************
339-
* Determine if smember has access to private members of this declaration.
340-
*/
341-
bool hasPrivateAccess(AggregateDeclaration *ad, Dsymbol *smember)
342-
{
343-
if (smember)
344-
{
345-
AggregateDeclaration *cd = NULL;
346-
Dsymbol *smemberparent = smember->toParent();
347-
if (smemberparent)
348-
cd = smemberparent->isAggregateDeclaration();
349-
350-
#if LOG
351-
printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
352-
ad->toChars(), smember->toChars());
353-
#endif
354-
355-
if (ad == cd) // smember is a member of this class
356-
{
357-
#if LOG
358-
printf("\tyes 1\n");
359-
#endif
360-
return true; // so we get private access
361-
}
362-
363-
// If both are members of the same module, grant access
364-
while (1)
365-
{
366-
Dsymbol *sp = smember->toParent();
367-
if (sp->isFuncDeclaration() && smember->isFuncDeclaration())
368-
smember = sp;
369-
else
370-
break;
371-
}
372-
if (!cd && ad->toParent() == smember->toParent())
373-
{
374-
#if LOG
375-
printf("\tyes 2\n");
376-
#endif
377-
return true;
378-
}
379-
if (!cd && ad->getAccessModule() == smember->getAccessModule())
380-
{
381-
#if LOG
382-
printf("\tyes 3\n");
383-
#endif
384-
return true;
385-
}
386-
}
387-
#if LOG
388-
printf("\tno\n");
389-
#endif
390-
return false;
391-
}
392-
393139
/****************************************
394140
* Check access to d for expression e.d
395141
* Returns true if the declaration is not accessible.
@@ -398,50 +144,30 @@ bool checkAccess(Loc loc, Scope *sc, Expression *e, Declaration *d)
398144
{
399145
if (sc->flags & SCOPEnoaccesscheck)
400146
return false;
147+
if (d->isUnitTestDeclaration()) // Unittests are always accessible.
148+
return false;
401149

402150
#if LOG
403-
if (e)
404-
{
405-
printf("checkAccess(%s . %s)\n", e->toChars(), d->toChars());
406-
printf("\te->type = %s\n", e->type->toChars());
407-
}
408-
else
409-
{
410-
printf("checkAccess(%s)\n", d->toPrettyChars());
411-
}
151+
printf("[%s] checkAccess(%s)\n", loc.toChars(), d->toPrettyChars());
412152
#endif
413-
if(d->isUnitTestDeclaration())
414-
{
415-
// Unittests are always accessible.
153+
154+
// friend access
155+
if (d->getAccessModule() == sc->module)
416156
return false;
417-
}
418-
if (!e)
157+
158+
// check access rights
159+
if (d->prot().kind == PROTprivate ||
160+
d->prot().kind == PROTpackage && !hasPackageAccess(sc, d) ||
161+
d->prot().kind == PROTprotected && !hasProtectedAccess(sc, d))
419162
{
420-
if (d->prot().kind == PROTprivate && d->getAccessModule() != sc->module ||
421-
d->prot().kind == PROTpackage && !hasPackageAccess(sc, d))
422-
{
163+
AggregateDeclaration *ad = d->toParent2()->isAggregateDeclaration();
164+
if (ad)
165+
ad->error(loc, "member %s is not accessible from module %s",
166+
d->toChars(), sc->module->toChars());
167+
else
423168
error(loc, "%s %s is not accessible from module %s",
424169
d->kind(), d->toPrettyChars(), sc->module->toChars());
425-
return true;
426-
}
427-
}
428-
else if (e->type->ty == Tclass)
429-
{
430-
// Do access check
431-
ClassDeclaration *cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
432-
if (e->op == TOKsuper)
433-
{
434-
ClassDeclaration *cd2 = sc->func->toParent()->isClassDeclaration();
435-
if (cd2)
436-
cd = cd2;
437-
}
438-
return checkAccess(cd, loc, sc, d);
439-
}
440-
else if (e->type->ty == Tstruct)
441-
{
442-
// Do access check
443-
StructDeclaration *cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
444-
return checkAccess(cd, loc, sc, d);
170+
return true;
445171
}
446172
return false;
447173
}

0 commit comments

Comments
 (0)