VirtualBox

Changeset 3399 in kBuild for trunk


Ignore:
Timestamp:
Jul 2, 2020 11:35:23 AM (5 years ago)
Author:
bird
Message:

kmk/expreval.c: Don't pick up version compare operators in the middle of unquoted strings. Baked isspace into expr_map_get.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/expreval.c

    r3398 r3399  
    5959/** The max operand depth. */
    6060#define EXPR_MAX_OPERANDS   128
     61
     62/** Check if @a a_ch is a valid separator for a alphabetical binary
     63 *  operator, omitting isspace. */
     64#define EXPR_IS_OP_SEPARATOR_NO_SPACE(a_ch) \
     65    (ispunct((a_ch)) && (a_ch) != '@' && (a_ch) != '_'))
     66
     67/** Check if @a a_ch is a valid separator for a alphabetical binary operator. */
     68#define EXPR_IS_OP_SEPARATOR(a_ch) \
     69    (isspace((a_ch)) || EXPR_IS_OP_SEPARATOR_NO_SPACE(a_ch))
    6170
    6271
     
    181190*******************************************************************************/
    182191/** Operator start character map.
    183  * This indicates which characters that are starting operators and which aren't. */
     192 * This indicates which characters that are starting operators and which aren't.
     193 *
     194 * Bit 0: Indicates that this char is used in operators.
     195 * Bit 1: When bit 0 is clear, this indicates whitespace.
     196 *        When bit 1 is set, this indicates whether the operator can be used
     197 *        immediately next to an operand without any clear separation.
     198 * Bits 2 thru 7: Index into g_aExprOps of the first operator starting with
     199 *        this character.
     200 */
    184201static unsigned char g_auchOpStartCharMap[256];
    185202/** Whether we've initialized the map. */
     
    18201837static const EXPROP g_ExprEndOfExpOp =
    18211838{
    1822               "", 0, '\0',    0,      0,    NULL
     1839            "", 0, '\0',    0,      0,    NULL
    18231840};
    18241841
     
    18411858        unsigned int ch = (unsigned int)g_aExprOps[i].szOp[0];
    18421859        if (!g_auchOpStartCharMap[ch])
    1843             g_auchOpStartCharMap[ch] = (i << 1) | 1;
    1844     }
     1860        {
     1861            g_auchOpStartCharMap[ch] = (i << 2) | 1;
     1862            if (!isalpha(ch))
     1863                g_auchOpStartCharMap[ch] |= 2; /* Need no clear separation from operands. */
     1864        }
     1865    }
     1866
     1867    /* whitespace (assumes C-like locale because I'm lazy): */
     1868#define SET_WHITESPACE(a_ch) do {  \
     1869        assert(g_auchOpStartCharMap[(unsigned char)(a_ch)] == 0); \
     1870        g_auchOpStartCharMap[(unsigned char)(a_ch)] |= 2; \
     1871    } while (0)
     1872    SET_WHITESPACE(' ');
     1873    SET_WHITESPACE('\t');
     1874    SET_WHITESPACE('\n');
     1875    SET_WHITESPACE('\r');
     1876    SET_WHITESPACE('\v');
     1877    SET_WHITESPACE('\f');
    18451878
    18461879    g_fExprInitializedMap = 1;
     
    18511884 * Looks up a character in the map.
    18521885 *
    1853  * @returns the value for that char.
    1854  * @retval  0 if not a potential opcode start char.
    1855  * @retval  non-zero if it's a potential operator. The low bit is always set
    1856  *          while the remaining 7 bits is the index into the operator table
    1857  *          of the first match.
    1858  *
     1886 * @returns the value for that char, see g_auchOpStartCharMap for details.
    18591887 * @param   ch      The character.
    18601888 */
     
    18771905    char ch = *psz;
    18781906    unsigned i;
    1879 
    1880     for (i = uchVal >> 1; i < sizeof(g_aExprOps) / sizeof(g_aExprOps[0]); i++)
     1907    assert((uchVal & 2) == (isalpha(ch) ? 0 : 2));
     1908
     1909    for (i = uchVal >> 2; i < sizeof(g_aExprOps) / sizeof(g_aExprOps[0]); i++)
    18811910    {
    18821911        /* compare the string... */
     
    19001929        if (fUnary == (g_aExprOps[i].cArgs == 1))
    19011930        {
    1902             /* got a match! */
    1903             return &g_aExprOps[i];
     1931            /* Check if we've got the needed operand separation: */
     1932            if (   (uchVal & 2)
     1933                || EXPR_IS_OP_SEPARATOR(psz[g_aExprOps[i].cchOp]))
     1934            {
     1935                /* got a match! */
     1936                return &g_aExprOps[i];
     1937            }
    19041938        }
    19051939    }
     
    19581992
    19591993        /* spaces */
    1960         while (ISSPACE(*psz))
     1994        unsigned char uchVal;
     1995        char ch;
     1996        while (((uchVal = expr_map_get((ch = *psz))) & 3) == 2)
    19611997            psz++;
     1998
    19621999        /* see what we've got. */
    1963         if (*psz)
     2000        if (ch)
    19642001        {
    1965             unsigned char uchVal = expr_map_get(*psz);
    1966             if (uchVal)
     2002            if (uchVal & 1)
    19672003                pOp = expr_lookup_op(psz, uchVal, 0 /* fUnary */);
    19682004            if (!pOp)
     
    20182054    PCEXPROP      pOp;
    20192055    char const   *psz = pThis->psz;
     2056    char          ch;
    20202057
    20212058    /*
    20222059     * Eat white space and make sure there is something after it.
    20232060     */
    2024     while (ISSPACE(*psz))
     2061    while (((uchVal = expr_map_get((ch = *psz))) & 3) == 2)
    20252062        psz++;
    2026     if (!*psz)
     2063    if (ch == '\0')
    20272064    {
    20282065        expr_error(pThis, "Unexpected end of expression");
     
    20342071     */
    20352072    pOp = NULL;
    2036     uchVal = expr_map_get(*psz);
    2037     if (uchVal)
     2073    if (uchVal & 1)
    20382074        pOp = expr_lookup_op(psz, uchVal, 1 /* fUnary */);
    20392075    if (pOp)
     
    20632099
    20642100        rc = kExprRet_Ok;
    2065         if (*psz == '"')
     2101        if (ch == '"')
    20662102        {
    20672103            pszStart = ++psz;
    2068             while (*psz && *psz != '"')
     2104            while ((ch = *psz) != '\0' && ch != '"')
    20692105                psz++;
    20702106            expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_QuotedString);
    2071             if (*psz)
     2107            if (ch != '\0')
    20722108                psz++;
    20732109        }
    2074         else if (*psz == '\'')
     2110        else if (ch == '\'')
    20752111        {
    20762112            pszStart = ++psz;
    2077             while (*psz && *psz != '\'')
     2113            while ((ch = *psz) != '\0' && ch != '\'')
    20782114                psz++;
    20792115            expr_var_init_substring(&pThis->aVars[++pThis->iVar], pszStart, psz - pszStart, kExprVar_QuotedSimpleString);
    2080             if (*psz)
     2116            if (ch != '\0')
    20812117                psz++;
    20822118        }
     
    20862122            int     iPar = -1;
    20872123            char    chEndPar = '\0';
    2088             char    ch, ch2;
    20892124
    20902125            pszStart = psz;
    20912126            while ((ch = *psz) != '\0')
    20922127            {
     2128                char ch2;
     2129
    20932130                /* $(adsf) or ${asdf} needs special handling. */
    20942131                if (    ch == '$'
     
    21122149                else if (!chEndPar)
    21132150                {
    2114                     /** @todo combine isspace and expr_map_get! */
    2115                     unsigned chVal = expr_map_get(ch);
    2116                     if (chVal)
     2151                    uchVal = expr_map_get(ch);
     2152                    if (uchVal == 0)
     2153                    { /*likely*/ }
     2154                    else if ((uchVal & 3) == 2 /*isspace*/)
     2155                        break;
     2156                    else if (   (uchVal & 1)
     2157                             && psz != pszStart  /* not at the start */
     2158                             && (   (uchVal & 2) /* operator without separator needs */
     2159                                 || EXPR_IS_OP_SEPARATOR_NO_SPACE(psz[-1])))
    21172160                    {
    21182161                        pOp = expr_lookup_op(psz, uchVal, 0 /* fUnary */);
     
    21202163                            break;
    21212164                    }
    2122                     if (ISSPACE(ch))
    2123                         break;
    21242165                }
    21252166
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette