*** ../bash-5.2-patched/lib/glob/sm_loop.c 2021-08-03 10:24:49.000000000 -0400 --- lib/glob/sm_loop.c 2022-11-17 15:42:42.000000000 -0500 *************** *** 344,347 **** --- 344,352 ---- return (FNM_NOMATCH); + /* If we are matching pathnames, we can't match a slash with a + bracket expression. */ + if (sc == L('/') && (flags & FNM_PATHNAME)) + return (FNM_NOMATCH); + /* `?' cannot match `.' or `..' if it is the first character of the string or if it is the first character following a slash and *************** *** 404,407 **** --- 409,414 ---- } + #define SLASH_PATHNAME(c) (c == L('/') && (flags & FNM_PATHNAME)) + /* Use prototype definition here because of type promotion. */ static CHAR * *************** *** 452,455 **** --- 459,468 ---- pc = FOLD (p[1]); p += 4; + + /* Finding a slash in a bracket expression means you have to + match the bracket as an ordinary character (see below). */ + if (pc == L('/') && (flags & FNM_PATHNAME)) + return ((test == L('[')) ? savep : (CHAR *)0); /*]*/ + if (COLLEQUIV (test, pc)) { *************** *** 464,467 **** --- 477,484 ---- if (c == L('\0')) return ((test == L('[')) ? savep : (CHAR *)0); /*]*/ + else if (c == L('/') && (flags & FNM_PATHNAME)) + return ((test == L('[')) ? savep : (CHAR *)0); /*]*/ + else if (c == L(']')) + break; c = FOLD (c); continue; *************** *** 476,484 **** pc = 0; /* make sure invalid char classes don't match. */ /* Find end of character class name */ ! for (close = p + 1; *close != '\0'; close++) if (*close == L(':') && *(close+1) == L(']')) break; ! if (*close != L('\0')) { ccname = (CHAR *)malloc ((close - p) * sizeof (CHAR)); --- 493,501 ---- pc = 0; /* make sure invalid char classes don't match. */ /* Find end of character class name */ ! for (close = p + 1; *close != '\0' && SLASH_PATHNAME(*close) == 0; close++) if (*close == L(':') && *(close+1) == L(']')) break; ! if (*close != L('\0') && SLASH_PATHNAME(*close) == 0) { ccname = (CHAR *)malloc ((close - p) * sizeof (CHAR)); *************** *** 527,530 **** --- 544,549 ---- if (c == L('\0')) return ((test == L('[')) ? savep : (CHAR *)0); + else if (c == L('/') && (flags & FNM_PATHNAME)) + return ((test == L('[')) ? savep : (CHAR *)0); /*]*/ else if (c == L(']')) break; *************** *** 566,569 **** --- 585,598 ---- return ((test == L('[')) ? savep : (CHAR *)0); + /* POSIX.2 2.13.3 says: `If a character is found following an + unescaped character before a corresponding + is found, the open bracket shall be treated + as an ordinary character.' If we find a slash in a bracket + expression and the flags indicate we're supposed to be treating the + string like a pathname, we have to treat the `[' as just a character + to be matched. */ + if (c == L('/') && (flags & FNM_PATHNAME)) + return ((test == L('[')) ? savep : (CHAR *)0); + c = *p++; c = FOLD (c); *************** *** 571,578 **** if (c == L('\0')) return ((test == L('[')) ? savep : (CHAR *)0); ! ! if ((flags & FNM_PATHNAME) && c == L('/')) ! /* [/] can never match when matching a pathname. */ ! return (CHAR *)0; /* This introduces a range, unless the `-' is the last --- 600,605 ---- if (c == L('\0')) return ((test == L('[')) ? savep : (CHAR *)0); ! else if (c == L('/') && (flags & FNM_PATHNAME)) ! return ((test == L('[')) ? savep : (CHAR *)0); /* This introduces a range, unless the `-' is the last *************** *** 585,589 **** cend = *p++; if (cend == L('\0')) ! return (CHAR *)0; if (cend == L('[') && *p == L('.')) { --- 612,618 ---- cend = *p++; if (cend == L('\0')) ! return ((test == L('[')) ? savep : (CHAR *)0); ! else if (cend == L('/') && (flags & FNM_PATHNAME)) ! return ((test == L('[')) ? savep : (CHAR *)0); if (cend == L('[') && *p == L('.')) { *************** *** 637,640 **** --- 666,671 ---- if (c == L('\0')) return ((test == L('[')) ? savep : (CHAR *)0); + else if (c == L('/') && (flags & FNM_PATHNAME)) + return ((test == L('[')) ? savep : (CHAR *)0); oc = c; *************** *** 644,648 **** brcnt++; brchrp = p++; /* skip over the char after the left bracket */ ! if ((c = *p) == L('\0')) return ((test == L('[')) ? savep : (CHAR *)0); /* If *brchrp == ':' we should check that the rest of the characters --- 675,682 ---- brcnt++; brchrp = p++; /* skip over the char after the left bracket */ ! c = *p; ! if (c == L('\0')) ! return ((test == L('[')) ? savep : (CHAR *)0); ! else if (c == L('/') && (flags & FNM_PATHNAME)) return ((test == L('[')) ? savep : (CHAR *)0); /* If *brchrp == ':' we should check that the rest of the characters *************** *** 667,670 **** --- 701,706 ---- if (*p == '\0') return (CHAR *)0; + else if (*p == L('/') && (flags & FNM_PATHNAME)) + return ((test == L('[')) ? savep : (CHAR *)0); /* XXX 1003.2d11 is unclear if this is right. */ ++p;