postgres.git / summary / log / commit / refs

commit    d9a4cce29d563e4e6f6eec8b807736d98b1ad553
Author:   Andrew Gierth <rhodiumtoad@postgresql.org>
Date:     Sat Apr 25 04:09:30 2020 +0000
First released in: 13.0, 9.5.22, 9.6.18, 10.13, 11.8, 12.3

    Fix error case for CREATE ROLE ... IN ROLE.
    
    CreateRole() was passing a Value node, not a RoleSpec node, for the
    newly-created role name when adding the role as a member of existing
    roles for the IN ROLE syntax.
    
    This mistake went unnoticed because the node in question is used only
    for error messages and is not accessed on non-error paths.
    
    In older pg versions (such as 9.5 where this was found), this results
    in an "unexpected node type" error in place of the real error. That
    node type check was removed at some point, after which the code would
    accidentally fail to fail on 64-bit platforms (on which accessing the
    Value node as if it were a RoleSpec would be mostly harmless) or give
    an "unexpected role type" error on 32-bit platforms.
    
    Fix the code to pass the correct node type, and add an lfirst_node
    assertion just in case.
    
    Per report on irc from user m1chelangelo.
    
    Backpatch all the way, because this error has been around for a long
    time.


src/backend/commands/user.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 87562683c83..1ef00d6e895 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -470,20 +470,31 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) /* * Add the new role to the specified existing roles. */ - foreach(item, addroleto) + if (addroleto) { - RoleSpec *oldrole = lfirst(item); - HeapTuple oldroletup = get_rolespec_tuple(oldrole); - Form_pg_authid oldroleform = (Form_pg_authid) GETSTRUCT(oldroletup); - Oid oldroleid = oldroleform->oid; - char *oldrolename = NameStr(oldroleform->rolname); - - AddRoleMems(oldrolename, oldroleid, - list_make1(makeString(stmt->role)), - list_make1_oid(roleid), - GetUserId(), false); + RoleSpec *thisrole = makeNode(RoleSpec); + List *thisrole_list = list_make1(thisrole); + List *thisrole_oidlist = list_make1_oid(roleid); + + thisrole->roletype = ROLESPEC_CSTRING; + thisrole->rolename = stmt->role; + thisrole->location = -1; - ReleaseSysCache(oldroletup); + foreach(item, addroleto) + { + RoleSpec *oldrole = lfirst(item); + HeapTuple oldroletup = get_rolespec_tuple(oldrole); + Form_pg_authid oldroleform = (Form_pg_authid) GETSTRUCT(oldroletup); + Oid oldroleid = oldroleform->oid; + char *oldrolename = NameStr(oldroleform->rolname); + + AddRoleMems(oldrolename, oldroleid, + thisrole_list, + thisrole_oidlist, + GetUserId(), false); + + ReleaseSysCache(oldroletup); + } } /* @@ -1503,7 +1514,7 @@ AddRoleMems(const char *rolename, Oid roleid, forboth(specitem, memberSpecs, iditem, memberIds) { - RoleSpec *memberRole = lfirst(specitem); + RoleSpec *memberRole = lfirst_node(RoleSpec, specitem); Oid memberid = lfirst_oid(iditem); HeapTuple authmem_tuple; HeapTuple tuple; [parent: 6c5f91616826]