VirtualBox

Changeset 55494 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Apr 28, 2015 7:18:15 PM (10 years ago)
Author:
vboxsync
Message:

Tought RTGetOptArgvFromString about escapes and fixed some RTGetOptArgvToString quoting table bugs.

Location:
trunk/src/VBox/Runtime
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/misc/getoptargv.cpp

    r44529 r55494  
    4747 * require quoting of.
    4848 */
    49 static uint8_t const g_abmQuoteChars[RTGETOPTARGV_CNV_QUOTE_MASK + 1][128/8] =
    50 {
    51     { 0xfe, 0xff, 0x0f, 0x00, 0x65, 0x00, 0x00, 0x50 },
    52     { 0xfe, 0xff, 0x0f, 0x00, 0xd7, 0x07, 0x00, 0xd8 },
     49static uint8_t
     50#ifndef IPRT_REGENERATE_QUOTE_CHARS
     51const
     52#endif
     53g_abmQuoteChars[RTGETOPTARGV_CNV_QUOTE_MASK + 1][16] =
     54{
     55    { 0xfe, 0xff, 0xff, 0xff, 0x65, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 },
     56    { 0xfe, 0xff, 0xff, 0xff, 0xd7, 0x07, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x50 },
    5357};
    5458
    5559
    56 #if 0   /* To re-generate the bitmaps. */
    57 #include <stdio.h>
     60#ifdef IPRT_REGENERATE_QUOTE_CHARS   /* To re-generate the bitmaps. */
     61# include <stdio.h>
    5862int main()
    5963{
     
    6670        } while (0)
    6771# define SET(ConstSuffix, ch) \
    68         ASMBitSet(&g_abmQuoteChars[RTGETOPTARGV_CNV_QUOTE_##ConstSuffix], (ch));
     72        do { \
     73            ASMBitSet(&g_abmQuoteChars[RTGETOPTARGV_CNV_QUOTE_##ConstSuffix], (ch)); \
     74            printf(#ConstSuffix ": %#x %d %c\n", (ch), (ch), (ch)); \
     75        } while (0)
    6976
    7077    /* just flag all the control chars as in need of quoting. */
     
    7683
    7784    /* MS CRT / CMD.EXE: */
    78     SET(MS_CRT, '"')
    79     SET(MS_CRT, '&')
    80     SET(MS_CRT, '>')
    81     SET(MS_CRT, '<')
    82     SET(MS_CRT, '|')
    83     SET(MS_CRT, '%')
     85    SET(MS_CRT, '"');
     86    SET(MS_CRT, '&');
     87    SET(MS_CRT, '>');
     88    SET(MS_CRT, '<');
     89    SET(MS_CRT, '|');
     90    SET(MS_CRT, '%');
    8491
    8592    /* Bourne shell: */
     
    105112    {
    106113        printf("    {");
    107         for (size_t iByte = 0; iByte < 8; iByte++)
     114        for (size_t iByte = 0; iByte < 16; iByte++)
    108115            printf(iByte == 0 ? " 0x%02x" : ", 0x%02x", g_abmQuoteChars[iType][iByte]);
    109116        printf(" },\n");
     
    111118    return 0;
    112119}
    113 #endif /* To re-generate the bitmaps. */
    114 
     120
     121#else /* !IPRT_REGENERATE_QUOTE_CHARS */
    115122
    116123/**
     
    262269        papszArgs[iArg++] = pszDst;
    263270
    264         /* Parse and copy the string over. */
     271        /*
     272         * Parse and copy the string over.
     273         */
    265274        RTUNICP CpQuote = 0;
    266275        RTUNICP Cp;
     
    276285                else if (rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators))
    277286                    break;
     287                else if (Cp != '\\')
     288                    pszDst = RTStrPutCp(pszDst, Cp);
    278289                else
     290                {
     291                    /* escaped char */
     292                    rc = RTStrGetCpEx(&pszSrc, &Cp);
     293                    if (RT_FAILURE(rc) || !Cp)
     294                        break;
    279295                    pszDst = RTStrPutCp(pszDst, Cp);
     296                }
    280297            }
    281298            else if (CpQuote != Cp)
    282                 pszDst = RTStrPutCp(pszDst, Cp);
     299            {
     300                if (Cp != '\\' || CpQuote == '\'')
     301                    pszDst = RTStrPutCp(pszDst, Cp);
     302                else
     303                {
     304                    /* escaped char */
     305                    rc = RTStrGetCpEx(&pszSrc, &Cp);
     306                    if (RT_FAILURE(rc) || !Cp)
     307                        break;
     308                    pszDst = RTStrPutCp(pszDst, Cp);
     309                }
     310            }
    283311            else
    284312                CpQuote = 0;
     
    511539}
    512540
     541#endif  /* !IPRT_REGENERATE_QUOTE_CHARS */
     542
  • trunk/src/VBox/Runtime/testcase/tstRTGetOptArgv.cpp

    r28800 r55494  
    3737
    3838
     39/*******************************************************************************
     40*   Global Variables                                                           *
     41*******************************************************************************/
     42static const struct
     43{
     44    /** The input string. */
     45    const char *pszInput;
     46    /** Separators, NULL if default. */
     47    const char *pszSeparators;
     48    /** The number of arguments. */
     49    int         cArgs;
     50    /** Expected argument vector. */
     51    const char *apszArgs[16];
     52    /** Expected quoted string, bourne shell. */
     53    const char *pszOutBourneSh;
     54    /** Expected quoted string, MSC CRT. */
     55    const char *pszOutMsCrt;
     56} g_aBourneTests[] =
     57{
     58    {
     59        "0 1 \"\"2'' '3' 4 5 '''''6' 7 8 9 10 11",
     60        NULL,
     61        12,
     62        {
     63             "0",
     64             "1",
     65             "2",
     66             "3",
     67             "4",
     68             "5",
     69             "6",
     70             "7",
     71             "8",
     72             "9",
     73             "10",
     74             "11",
     75             NULL, NULL, NULL, NULL,
     76        },
     77        "0 1 2 3 4 5 6 7 8 9 10 11",
     78        "0 1 2 3 4 5 6 7 8 9 10 11"
     79    },
     80    {
     81        "\t\" asdf \"  '\"'xyz  \"\t\"  '\n'  '\"'  \"'\"\n\r ",
     82        NULL,
     83        6,
     84        {
     85            " asdf ",
     86            "\"xyz",
     87            "\t",
     88            "\n",
     89            "\"",
     90            "\'",
     91            NULL, NULL,
     92            NULL, NULL, NULL, NULL,  NULL, NULL, NULL, NULL,
     93        },
     94        "' asdf ' '\"xyz' '\t' '\n' '\"' ''\"'\"''",
     95        "\" asdf \" \"\\\"xyz\" \"\t\" \"\n\" \"\\\"\" '"
     96    },
     97    {
     98        ":0::1::::2:3:4:5:",
     99        ":",
     100        6,
     101        {
     102            "0",
     103            "1",
     104            "2",
     105            "3",
     106            "4",
     107            "5",
     108            NULL, NULL,
     109            NULL, NULL, NULL, NULL,  NULL, NULL, NULL, NULL,
     110        },
     111        "0 1 2 3 4 5",
     112        "0 1 2 3 4 5"
     113    },
     114    {
     115        "0:1;2:3;4:5",
     116        ";;;;;;;;;;;;;;;;;;;;;;:",
     117        6,
     118        {
     119            "0",
     120            "1",
     121            "2",
     122            "3",
     123            "4",
     124            "5",
     125            NULL, NULL,
     126            NULL, NULL, NULL, NULL,  NULL, NULL, NULL, NULL,
     127        },
     128        "0 1 2 3 4 5",
     129        "0 1 2 3 4 5"
     130    },
     131    {
     132        "abcd 'a ' ' b' ' c '",
     133        NULL,
     134        4,
     135        {
     136            "abcd",
     137            "a ",
     138            " b",
     139            " c ",
     140            NULL, NULL, NULL, NULL,
     141            NULL, NULL, NULL, NULL,  NULL, NULL, NULL, NULL,
     142        },
     143        "abcd 'a ' ' b' ' c '",
     144        "abcd \"a \" \" b\" \" c \""
     145    },
     146    {
     147        "'a\n\\b' 'de'\"'\"'fg' h ''\"'\"''",
     148        NULL,
     149        4,
     150        {
     151            "a\n\\b",
     152            "de'fg",
     153            "h",
     154            "'",
     155            NULL, NULL, NULL, NULL,
     156            NULL, NULL, NULL, NULL,  NULL, NULL, NULL, NULL,
     157        },
     158        "'a\n\\b' 'de'\"'\"'fg' h ''\"'\"''",
     159        "\"a\n\\b\" de'fg h '"
     160    },
     161    {
     162        "arg1 \"arg2=\\\"zyx\\\"\"  'arg3=\\\\\\'",
     163        NULL,
     164        3,
     165        {
     166            "arg1",
     167            "arg2=\"zyx\"",
     168            "arg3=\\\\\\",
     169            NULL,  NULL, NULL, NULL, NULL,
     170            NULL, NULL, NULL, NULL,  NULL, NULL, NULL, NULL,
     171        },
     172        "arg1 'arg2=\"zyx\"' 'arg3=\\\\\\'",
     173        "arg1 \"arg2=\\\"zyx\\\"\" arg3=\\\\\\"
     174    },
     175};
     176
     177
     178static void tst3(void)
     179{
     180    /*
     181     * Bourne shell round-tripping.
     182     */
     183    RTTestISub("Round-trips / BOURNE_SH");
     184    for (unsigned i = 0; i < RT_ELEMENTS(g_aBourneTests); i++)
     185    {
     186        /* First */
     187        char **papszArgs1 = NULL;
     188        int    cArgs1     = -1;
     189        int rc = RTGetOptArgvFromString(&papszArgs1, &cArgs1, g_aBourneTests[i].pszInput, g_aBourneTests[i].pszSeparators);
     190        if (rc == VINF_SUCCESS)
     191        {
     192            if (cArgs1 != g_aBourneTests[i].cArgs)
     193                RTTestIFailed("g_aBourneTests[%i]: #1=%d, expected %d", i, cArgs1, g_aBourneTests[i].cArgs);
     194            for (int iArg = 0; iArg < cArgs1; iArg++)
     195                if (strcmp(papszArgs1[iArg], g_aBourneTests[i].apszArgs[iArg]) != 0)
     196                    RTTestIFailed("g_aBourneTests[%i]/#1: argv[%i] differs: got '%s', expected '%s' (RTGetOptArgvFromString(,,'%s', '%s'))",
     197                                  i, iArg, papszArgs1[iArg], g_aBourneTests[i].apszArgs[iArg],
     198                                  g_aBourneTests[i].pszInput, g_aBourneTests[i].pszSeparators);
     199            RTTESTI_CHECK_RETV(papszArgs1[cArgs1] == NULL);
     200
     201            /* Second */
     202            char *pszArgs2 = NULL;
     203            rc = RTGetOptArgvToString(&pszArgs2, papszArgs1, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);
     204            if (rc == VINF_SUCCESS)
     205            {
     206                if (strcmp(pszArgs2, g_aBourneTests[i].pszOutBourneSh))
     207                    RTTestIFailed("g_aBourneTests[%i]/2: '%s', expected '%s'", i, pszArgs2, g_aBourneTests[i].pszOutBourneSh);
     208
     209                /*
     210                 * Third
     211                 */
     212                char **papszArgs3 = NULL;
     213                int    cArgs3     = -1;
     214                rc = RTGetOptArgvFromString(&papszArgs3, &cArgs3, pszArgs2, NULL);
     215                if (rc == VINF_SUCCESS)
     216                {
     217                    if (cArgs3 != g_aBourneTests[i].cArgs)
     218                        RTTestIFailed("g_aBourneTests[%i]/3: %d, expected %d", i, cArgs3, g_aBourneTests[i].cArgs);
     219                    for (int iArg = 0; iArg < cArgs3; iArg++)
     220                        if (strcmp(papszArgs3[iArg], g_aBourneTests[i].apszArgs[iArg]) != 0)
     221                            RTTestIFailed("g_aBourneTests[%i]/3: argv[%i] differs: got '%s', expected '%s' (RTGetOptArgvFromString(,,'%s',))",
     222                                          i, iArg, papszArgs3[iArg], g_aBourneTests[i].apszArgs[iArg], pszArgs2);
     223                    RTTESTI_CHECK_RETV(papszArgs3[cArgs3] == NULL);
     224
     225                    /*
     226                     * Fourth
     227                     */
     228                    char *pszArgs4 = NULL;
     229                    rc = RTGetOptArgvToString(&pszArgs4, papszArgs3, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);
     230                    if (rc == VINF_SUCCESS)
     231                    {
     232                        if (strcmp(pszArgs4, pszArgs2))
     233                            RTTestIFailed("g_aBourneTests[%i]/4: '%s' does not match #4='%s'", i, pszArgs2, pszArgs4);
     234                        RTStrFree(pszArgs4);
     235                    }
     236                    else
     237                        RTTestIFailed("g_aBourneTests[%i]/4: RTGetOptArgvToString() -> %Rrc", i, rc);
     238                    RTGetOptArgvFree(papszArgs3);
     239                }
     240                else
     241                    RTTestIFailed("g_aBourneTests[%i]/3: RTGetOptArgvFromString() -> %Rrc", i, rc);
     242                RTStrFree(pszArgs2);
     243            }
     244            else
     245                RTTestIFailed("g_aBourneTests[%i]/2: RTGetOptArgvToString() -> %Rrc", i, rc);
     246            RTGetOptArgvFree(papszArgs1);
     247        }
     248        else
     249            RTTestIFailed("g_aBourneTests[%i]/1: RTGetOptArgvFromString(,,'%s', '%s') -> %Rrc",
     250                          i, g_aBourneTests[i].pszInput, g_aBourneTests[i].pszSeparators, rc);
     251    }
     252
     253}
     254
     255
    39256static void tst2(void)
    40257{
     
    78295    }
    79296
    80 
    81     RTTestISub("RTGetOptArgvToString / BOURNE_SH");
    82 
    83     static const struct
    84     {
    85         const char * const      apszArgs[5];
    86         const char             *pszCmdLine;
    87     } s_aBournShTests[] =
    88     {
    89         {
    90             { "abcd", "a ", " b", " c ", NULL },
    91             "abcd 'a ' ' b' ' c '"
    92         },
    93         {
    94             { "a\n\\b", "de'fg", "h", "'", NULL },
    95             "'a\n\\b' 'de'\"'\"'fg' h ''\"'\"''"
    96         }
    97     };
    98 
    99     for (size_t i = 0; i < RT_ELEMENTS(s_aBournShTests); i++)
     297    for (size_t i = 0; i < RT_ELEMENTS(g_aBourneTests); i++)
    100298    {
    101299        char *pszCmdLine = NULL;
    102         int rc = RTGetOptArgvToString(&pszCmdLine, s_aBournShTests[i].apszArgs, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);
     300        int rc = RTGetOptArgvToString(&pszCmdLine, g_aBourneTests[i].apszArgs, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
    103301        RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS);
    104         if (strcmp(s_aBournShTests[i].pszCmdLine, pszCmdLine))
    105             RTTestIFailed("g_aTest[%i] failed:\n"
     302        if (strcmp(g_aBourneTests[i].pszOutMsCrt, pszCmdLine))
     303            RTTestIFailed("g_aBourneTests[%i] failed:\n"
    106304                          " got      |%s|\n"
    107305                          " expected |%s|\n",
    108                           i, pszCmdLine, s_aBournShTests[i].pszCmdLine);
     306                          i, pszCmdLine, g_aBourneTests[i].pszOutMsCrt);
    109307        RTStrFree(pszCmdLine);
    110308    }
    111309
    112310
    113     RTTestISub("RTGetOptArgvToString <-> RTGetOptArgvFromString");
    114 
    115     for (size_t i = 0; i < RT_ELEMENTS(s_aBournShTests); i++)
     311
     312    RTTestISub("RTGetOptArgvToString / BOURNE_SH");
     313
     314    for (size_t i = 0; i < RT_ELEMENTS(g_aBourneTests); i++)
    116315    {
    117316        char *pszCmdLine = NULL;
    118         int rc = RTGetOptArgvToString(&pszCmdLine, s_aBournShTests[i].apszArgs, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);
     317        int rc = RTGetOptArgvToString(&pszCmdLine, g_aBourneTests[i].apszArgs, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);
    119318        RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS);
    120 
    121         char  **papszArgs;
    122         int     cArgs;
    123         rc = RTGetOptArgvFromString(&papszArgs, &cArgs, pszCmdLine, NULL);
    124         RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS);
    125 
    126         size_t j = 0;
    127         while (papszArgs[j] && s_aBournShTests[i].apszArgs[j])
    128         {
    129             if (strcmp(papszArgs[j], s_aBournShTests[i].apszArgs[j]))
    130                 RTTestIFailed("Test #%u, argument #%u mismatch:\n"
    131                               " FromString: |%s| (got)\n"
    132                               " ToString:   |%s| (expected)\n",
    133                               i, j, papszArgs[j], s_aBournShTests[i].apszArgs[j]);
    134 
    135             /* next */
    136             j++;
    137         }
    138         RTTESTI_CHECK(papszArgs[j] == NULL);
    139         RTTESTI_CHECK(s_aBournShTests[i].apszArgs[j] == NULL);
    140 
    141         RTGetOptArgvFree(papszArgs);
     319        if (strcmp(g_aBourneTests[i].pszOutBourneSh, pszCmdLine))
     320            RTTestIFailed("g_aBourneTests[%i] failed:\n"
     321                          " got      |%s|\n"
     322                          " expected |%s|\n",
     323                          i, pszCmdLine, g_aBourneTests[i].pszOutBourneSh);
    142324        RTStrFree(pszCmdLine);
    143325    }
     
    204386    RTTESTI_CHECK_RETV(!papszArgs[6]);
    205387    RTGetOptArgvFree(papszArgs);
     388
     389    /*
     390     * Tests from the list.
     391     */
     392    for (unsigned i = 0; i < RT_ELEMENTS(g_aBourneTests); i++)
     393    {
     394        papszArgs = NULL;
     395        cArgs = -1;
     396        int rc = RTGetOptArgvFromString(&papszArgs, &cArgs, g_aBourneTests[i].pszInput, g_aBourneTests[i].pszSeparators);
     397        if (rc == VINF_SUCCESS)
     398        {
     399            if (cArgs == g_aBourneTests[i].cArgs)
     400            {
     401                for (int iArg = 0; iArg < cArgs; iArg++)
     402                    if (strcmp(papszArgs[iArg], g_aBourneTests[i].apszArgs[iArg]) != 0)
     403                        RTTestIFailed("g_aBourneTests[%i]: argv[%i] differs: got '%s', expected '%s' (RTGetOptArgvFromString(,,'%s', '%s'))",
     404                                      i, iArg, papszArgs[iArg], g_aBourneTests[i].apszArgs[iArg],
     405                                      g_aBourneTests[i].pszInput, g_aBourneTests[i].pszSeparators);
     406                RTTESTI_CHECK_RETV(papszArgs[cArgs] == NULL);
     407            }
     408            else
     409                RTTestIFailed("g_aBourneTests[%i]: cArgs=%u, expected %u for RTGetOptArgvFromString(,,'%s', '%s')",
     410                              i, cArgs, g_aBourneTests[i].cArgs, g_aBourneTests[i].pszInput, g_aBourneTests[i].pszSeparators);
     411            RTGetOptArgvFree(papszArgs);
     412        }
     413        else
     414            RTTestIFailed("g_aBourneTests[%i]: RTGetOptArgvFromString(,,'%s', '%s') -> %Rrc",
     415                          i, g_aBourneTests[i].pszInput, g_aBourneTests[i].pszSeparators, rc);
     416    }
    206417}
     418
    207419
    208420int main()
     
    222434    tst1();
    223435    tst2();
     436    tst3();
    224437
    225438    /*
Note: See TracChangeset for help on using the changeset viewer.

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