Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8488f25

Browse files
committed
Upgrade parsing code for ACLs to be less hokey and more cognizant of
the actual logical structure and quoting rules being used. Fixes bugreported by Chris K-L on 7/8/03.
1 parent1c6eba4 commit8488f25

File tree

1 file changed

+151
-36
lines changed

1 file changed

+151
-36
lines changed

‎src/bin/pg_dump/dumputils.c

Lines changed: 151 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.5 2003/07/24 15:52:53 petere Exp $
10+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.6 2003/07/31 17:21:57 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -19,12 +19,15 @@
1919
#include"parser/keywords.h"
2020

2121

22+
#definesupports_grant_options(version) ((version) >= 70400)
23+
24+
staticboolparseAclArray(constchar*acls,char***itemarray,int*nitems);
2225
staticboolparseAclItem(constchar*item,constchar*type,constchar*name,
2326
intremoteVersion,
2427
PQExpBuffergrantee,PQExpBuffergrantor,
2528
PQExpBufferprivs,PQExpBufferprivswgo);
29+
staticchar*copyAclUserName(PQExpBufferoutput,char*input);
2630
staticvoidAddAcl(PQExpBufferaclbuf,constchar*keyword);
27-
#definesupports_grant_options(version) ((version) >= 70400)
2831

2932

3033
/*
@@ -185,15 +188,23 @@ buildACLCommands(const char *name, const char *type,
185188
intremoteVersion,
186189
PQExpBuffersql)
187190
{
188-
char*aclbuf,
189-
*tok;
191+
char**aclitems;
192+
intnaclitems;
193+
inti;
190194
PQExpBuffergrantee,grantor,privs,privswgo;
191195
PQExpBufferfirstsql,secondsql;
192196
boolfound_owner_privs= false;
193197

194198
if (strlen(acls)==0)
195199
return true;/* object has default permissions */
196200

201+
if (!parseAclArray(acls,&aclitems,&naclitems))
202+
{
203+
if (aclitems)
204+
free(aclitems);
205+
return false;
206+
}
207+
197208
grantee=createPQExpBuffer();
198209
grantor=createPQExpBuffer();
199210
privs=createPQExpBuffer();
@@ -217,27 +228,10 @@ buildACLCommands(const char *name, const char *type,
217228
appendPQExpBuffer(firstsql,"REVOKE ALL ON %s %s FROM PUBLIC;\n",
218229
type,name);
219230

220-
/* Make a working copy of acls so we can use strtok */
221-
aclbuf=strdup(acls);
222-
223-
/* Scan comma-separated ACL items */
224-
for (tok=strtok(aclbuf,",");tok!=NULL;tok=strtok(NULL,","))
231+
/* Scan individual ACL items */
232+
for (i=0;i<naclitems;i++)
225233
{
226-
size_ttoklen;
227-
228-
/*
229-
* Token may start with '{' and/or '"'. Actually only the start
230-
* of the string should have '{', but we don't verify that.
231-
*/
232-
if (*tok=='{')
233-
tok++;
234-
if (*tok=='"')
235-
tok++;
236-
toklen=strlen(tok);
237-
while (toklen >=0&& (tok[toklen-1]=='"'||tok[toklen-1]=='}'))
238-
tok[toklen---1]='\0';
239-
240-
if (!parseAclItem(tok,type,name,remoteVersion,
234+
if (!parseAclItem(aclitems[i],type,name,remoteVersion,
241235
grantee,grantor,privs,privswgo))
242236
return false;
243237

@@ -327,7 +321,6 @@ buildACLCommands(const char *name, const char *type,
327321
type,name,fmtId(owner));
328322
}
329323

330-
free(aclbuf);
331324
destroyPQExpBuffer(grantee);
332325
destroyPQExpBuffer(grantor);
333326
destroyPQExpBuffer(privs);
@@ -337,15 +330,105 @@ buildACLCommands(const char *name, const char *type,
337330
destroyPQExpBuffer(firstsql);
338331
destroyPQExpBuffer(secondsql);
339332

333+
free(aclitems);
334+
340335
return true;
341336
}
342337

338+
/*
339+
* Deconstruct an ACL array (or actually any 1-dimensional Postgres array)
340+
* into individual items.
341+
*
342+
* On success, returns true and sets *itemarray and *nitems to describe
343+
* an array of individual strings. On parse failure, returns false;
344+
* *itemarray may exist or be NULL.
345+
*
346+
* NOTE: free'ing itemarray is sufficient to deallocate the working storage.
347+
*/
348+
staticbool
349+
parseAclArray(constchar*acls,char***itemarray,int*nitems)
350+
{
351+
intinputlen;
352+
char**items;
353+
char*strings;
354+
intcuritem;
355+
356+
/*
357+
* We expect input in the form of "{item,item,item}" where any item
358+
* is either raw data, or surrounded by double quotes (in which case
359+
* embedded characters including backslashes and quotes are backslashed).
360+
*
361+
* We build the result as an array of pointers followed by the actual
362+
* string data, all in one malloc block for convenience of deallocation.
363+
* The worst-case storage need is not more than one pointer and one
364+
* character for each input character (consider "{,,,,,,,,,,}").
365+
*/
366+
*itemarray=NULL;
367+
*nitems=0;
368+
inputlen=strlen(acls);
369+
if (inputlen<2||acls[0]!='{'||acls[inputlen-1]!='}')
370+
return false;/* bad input */
371+
items= (char**)malloc(inputlen* (sizeof(char*)+sizeof(char)));
372+
if (items==NULL)
373+
return false;/* out of memory */
374+
*itemarray=items;
375+
strings= (char*) (items+inputlen);
376+
377+
acls++;/* advance over initial '{' */
378+
curitem=0;
379+
while (*acls!='}')
380+
{
381+
if (*acls=='\0')
382+
return false;/* premature end of string */
383+
items[curitem]=strings;
384+
while (*acls!='}'&&*acls!=',')
385+
{
386+
if (*acls=='\0')
387+
return false;/* premature end of string */
388+
if (*acls!='"')
389+
*strings++=*acls++;/* copy unquoted data */
390+
else
391+
{
392+
/* process quoted substring */
393+
acls++;
394+
while (*acls!='"')
395+
{
396+
if (*acls=='\0')
397+
return false;/* premature end of string */
398+
if (*acls=='\\')
399+
{
400+
acls++;
401+
if (*acls=='\0')
402+
return false;/* premature end of string */
403+
}
404+
*strings++=*acls++;/* copy quoted data */
405+
}
406+
acls++;
407+
}
408+
}
409+
*strings++='\0';
410+
if (*acls==',')
411+
acls++;
412+
curitem++;
413+
}
414+
if (acls[1]!='\0')
415+
return false;/* bogus syntax (embedded '}') */
416+
*nitems=curitem;
417+
return true;
418+
}
343419

344420
/*
345-
* This will take an aclitem string of privilege code letters and
346-
* parse it into grantee, grantor, and privilege information. The
347-
* privilege information is split between privileges with grant option
348-
* (privswgo) and without (privs).
421+
* This will parse an aclitem string, having the general form
422+
*username=privilegecodes/grantor
423+
* or
424+
*group groupname=privilegecodes/grantor
425+
* (the /grantor part will not be present if pre-7.4 database).
426+
*
427+
* The returned grantee string will be the dequoted username or groupname
428+
* (preceded with "group " in the latter case). The returned grantor is
429+
* the dequoted grantor name or empty. Privilege characters are decoded
430+
* and split between privileges with grant option (privswgo) and without
431+
* (privs).
349432
*
350433
* Note: for cross-version compatibility, it's important to use ALL when
351434
* appropriate.
@@ -365,19 +448,19 @@ parseAclItem(const char *item, const char *type, const char *name,
365448

366449
buf=strdup(item);
367450

368-
/* user name is string up to = */
369-
eqpos=strchr(buf,'=');
370-
if (!eqpos)
451+
/* useror groupname is string up to = */
452+
eqpos=copyAclUserName(grantee,buf);
453+
if (*eqpos!='=')
371454
return false;
372-
*eqpos='\0';
373-
printfPQExpBuffer(grantee,"%s",buf);
374455

375456
/* grantor may be listed after / */
376457
slpos=strchr(eqpos+1,'/');
377458
if (slpos)
378459
{
379-
*slpos='\0';
380-
printfPQExpBuffer(grantor,"%s",slpos+1);
460+
*slpos++='\0';
461+
slpos=copyAclUserName(grantor,slpos);
462+
if (*slpos!='\0')
463+
return false;
381464
}
382465
else
383466
resetPQExpBuffer(grantor);
@@ -457,6 +540,38 @@ parseAclItem(const char *item, const char *type, const char *name,
457540
return true;
458541
}
459542

543+
/*
544+
* Transfer a user or group name starting at *input into the output buffer,
545+
* dequoting if needed. Returns a pointer to just past the input name.
546+
* The name is taken to end at an unquoted '=' or end of string.
547+
*/
548+
staticchar*
549+
copyAclUserName(PQExpBufferoutput,char*input)
550+
{
551+
resetPQExpBuffer(output);
552+
while (*input&&*input!='=')
553+
{
554+
if (*input!='"')
555+
appendPQExpBufferChar(output,*input++);
556+
else
557+
{
558+
input++;
559+
while (*input!='"')
560+
{
561+
if (*input=='\0')
562+
returninput;/* really a syntax error... */
563+
/*
564+
* There is no quoting convention here, thus we can't cope
565+
* with usernames containing double quotes. Keep this code
566+
* in sync with putid() in backend's acl.c.
567+
*/
568+
appendPQExpBufferChar(output,*input++);
569+
}
570+
input++;
571+
}
572+
}
573+
returninput;
574+
}
460575

461576
/*
462577
* Append a privilege keyword to a keyword list, inserting comma if needed.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp