VirtualBox

Changeset 93401 in vbox for trunk


Ignore:
Timestamp:
Jan 21, 2022 11:41:27 PM (3 years ago)
Author:
vboxsync
Message:

SharedClipboard/win: Fixed off by 2 calculation in SharedClipboardWinConvertMIMEToCFHTML as well as a testcase for it. Made SharedClipboardWinConvertCFHTMLToMIME accept zero length fragments because SharedClipboardWinConvertMIMEToCFHTML can produce them. bugref:10160

Location:
trunk/src/VBox
Files:
4 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp

    r93399 r93401  
    513513            if (   offStart > 0
    514514                && offEnd > 0
    515                 && offEnd > offStart
     515                && offEnd >= offStart
    516516                && offEnd <= cch)
    517517            {
     
    594594    Assert(cb);
    595595
    596     /* construct CF_HTML formatted string */
    597 
    598     /* Check that input is zero terminated. */
    599     /** @todo r=bird: Check that it's valid UTF-8 encoded too. */
    600     size_t cchFragment;
    601     int rc = RTStrNLenEx(pszSource, cb, &cchFragment);
    602     if (!RT_SUCCESS(rc))
     596    /*
     597     * Check that input UTF-8 and properly zero terminated.
     598     * Note! The zero termination may come earlier than 'cb' - 1, that's fine.
     599     */
     600    int rc = RTStrValidateEncodingEx(pszSource, cb, RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
     601    if (RT_SUCCESS(rc))
     602    { /* likely */ }
     603    else
    603604    {
    604605        LogRelFlowFunc(("Error: invalid source fragment. rc = %Rrc\n", rc));
    605         return VERR_INVALID_PARAMETER;
    606     }
     606        return rc;
     607    }
     608    size_t const cchFragment = strlen(pszSource); /* Unfortunately the validator doesn't return the length. */
    607609
    608610    /*
    609     @StartHtml - pos before <html>
    610     @EndHtml - whole size of text excluding ending zero char
    611     @StartFragment - pos after <!--StartFragment-->
    612     @EndFragment - pos before <!--EndFragment-->
    613     @note: all values includes CR\LF inserted into text
    614     Calculations:
    615     Header length = format Length + (3*6('digits')) - 2('%s') = format length + 16 (control value - 183)
    616     EndHtml  = Header length + fragment length
    617     StartHtml = 105(constant)
    618     StartFragment = 143(constant)
    619     EndFragment  = Header length + fragment length - 40(ending length)
    620     */
     611     * @StartHtml     - Absolute offset of <html>
     612     * @EndHtml       - Size of the whole resulting text (excluding ending zero char)
     613     * @StartFragment - Absolute position after <!--StartFragment-->
     614     * @EndFragment   - Absolute position of <!--EndFragment-->
     615     *
     616     * Note! The offset are zero padded to max width so we don't have any variations due to those.
     617     * Note! All values includes CRLFs inserted into text.
     618     *
     619     * Calculations:
     620     *   Header length = Format sample length - 2 ('%s')
     621     *   EndHtml       = Header length + fragment length
     622     *   StartHtml     = 101(constant)
     623     *   StartFragment = 137(constant)
     624     *   EndFragment   = Header length + fragment length - 38 (ending length)
     625     */
    621626    static const char s_szFormatSample[] =
    622627    /*   0:   */ "Version:1.0\r\n"
     
    631636    /* 137+2: */ "<!--EndFragment-->\r\n"
    632637    /* 157+2: */ "</body>\r\n"
    633     /* 166+2: */ "</html>\r\n";
    634     /* 175+2: */
     638    /* 166+2: */ "</html>\r\n"
     639    /* 175+2: */ ;
    635640    AssertCompile(sizeof(s_szFormatSample) == 175 + 2 + 1);
    636641
    637     /* calculate parameters of CF_HTML header */
    638     size_t cchHeader      = sizeof(s_szFormatSample) - 1;
    639     size_t offEndHtml     = cchHeader + cchFragment;
    640     size_t offEndFragment = cchHeader + cchFragment - 38; /* 175-137 = 38 */
     642    /* Calculate parameters of the CF_HTML header */
     643    size_t const cchHeader      = sizeof(s_szFormatSample) - 2 /*%s*/ - 1 /*'\0'*/;
     644    size_t const offEndHtml     = cchHeader + cchFragment;
     645    size_t const offEndFragment = cchHeader + cchFragment - 38; /* 175-137 = 38 */
    641646    char *pszResult = (char *)RTMemAlloc(offEndHtml + 1);
    642     if (pszResult == NULL)
    643     {
    644         LogRelFlowFunc(("Error: Cannot allocate memory for result buffer. rc = %Rrc\n"));
    645         return VERR_NO_MEMORY;
    646     }
    647 
    648     /* format result CF_HTML string */
    649     size_t cchFormatted = RTStrPrintf(pszResult, offEndHtml + 1,
    650                                       s_szFormatSample, offEndHtml, offEndFragment, pszSource);
     647    AssertLogRelReturn(pszResult, VERR_NO_MEMORY);
     648
     649    /* Format resulting CF_HTML string: */
     650    size_t cchFormatted = RTStrPrintf(pszResult, offEndHtml + 1, s_szFormatSample, offEndHtml, offEndFragment, pszSource);
    651651    Assert(offEndHtml == cchFormatted);
    652652
    653653#ifdef VBOX_STRICT
    654     /* Control calculations. check consistency.*/
     654    /*
     655     * Check the calculations.
     656     */
     657
     658    /* check 'StartFragment:' value */
    655659    static const char s_szStartFragment[] = "<!--StartFragment-->";
    656     static const char s_szEndFragment[] = "<!--EndFragment-->";
    657 
    658     /* check 'StartFragment:' value */
    659660    const char *pszRealStartFragment = RTStrStr(pszResult, s_szStartFragment);
    660661    Assert(&pszRealStartFragment[sizeof(s_szStartFragment) - 1] - pszResult == 137);
    661662
    662663    /* check 'EndFragment:' value */
     664    static const char s_szEndFragment[] = "<!--EndFragment-->";
    663665    const char *pszRealEndFragment = RTStrStr(pszResult, s_szEndFragment);
    664666    Assert((size_t)(pszRealEndFragment - pszResult) == offEndFragment);
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/Makefile.kmk

    r93115 r93401  
    5353        $(PATH_ROOT)/src/VBox/HostServices/common/message.cpp \
    5454        tstClipboardServiceImpl.cpp
     55 tstClipboardServiceImpl_SOURCES.win = \
     56        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp
    5557 tstClipboardServiceImpl_LIBS     = $(LIB_RUNTIME)
    5658 tstClipboardServiceImpl_CLEAN    = $(tstClipboardServiceImpl_0_OUTDIR)/tstClipboardServiceImpl.run
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceImpl.cpp

    r93115 r93401  
    1919
    2020#include <VBox/HostServices/VBoxClipboardSvc.h>
     21#ifdef RT_OS_WINDOWS
     22# include <VBox/GuestHost/SharedClipboard-win.h>
     23#endif
    2124
    2225#include <iprt/assert.h>
     
    6871
    6972    RTTestISub("Setting up client ...");
     73    RTTestIDisableAssertions();
     74
    7075    rc = setupTable(&table);
    7176    RTTESTI_CHECK_MSG_RETV(RT_SUCCESS(rc), ("rc=%Rrc\n", rc));
     
    7681    rc = shClSvcClientInit(&g_Client, 1 /* clientId */);
    7782    RTTESTI_CHECK_RC_OK(rc);
     83
     84    RTTestIRestoreAssertions();
    7885}
     86
     87#ifdef RT_OS_WINDOWS
     88# include "VBoxOrgCfHtml1.h"    /* From chrome 97.0.4692.71 */
     89# include "VBoxOrgMimeHtml1.h"
     90
     91static void testHtmlCf(void)
     92{
     93    RTTestISub("CF_HTML");
     94
     95    char    *pszOutput = NULL;
     96    uint32_t cbOutput  = UINT32_MAX/2;
     97    RTTestIDisableAssertions();
     98    RTTESTI_CHECK_RC(SharedClipboardWinConvertCFHTMLToMIME("", 0, &pszOutput, &cbOutput), VERR_INVALID_PARAMETER);
     99    RTTestIRestoreAssertions();
     100
     101    pszOutput = NULL;
     102    cbOutput  = UINT32_MAX/2;
     103    RTTESTI_CHECK_RC(SharedClipboardWinConvertCFHTMLToMIME((char *)&g_abVBoxOrgCfHtml1[0], g_cbVBoxOrgCfHtml1,
     104                                                           &pszOutput, &cbOutput), VINF_SUCCESS);
     105    RTTESTI_CHECK(cbOutput == g_cbVBoxOrgMimeHtml1);
     106    RTTESTI_CHECK(memcmp(pszOutput, g_abVBoxOrgMimeHtml1, cbOutput) == 0);
     107    RTMemFree(pszOutput);
     108
     109
     110    static RTSTRTUPLE const s_aRoundTrips[] =
     111    {
     112        { RT_STR_TUPLE("") },
     113        { RT_STR_TUPLE("1") },
     114        { RT_STR_TUPLE("12") },
     115        { RT_STR_TUPLE("123") },
     116        { RT_STR_TUPLE("1234") },
     117        { RT_STR_TUPLE("12345") },
     118        { RT_STR_TUPLE("123456") },
     119        { RT_STR_TUPLE("1234567") },
     120        { RT_STR_TUPLE("12345678") },
     121        { RT_STR_TUPLE("123456789") },
     122        { RT_STR_TUPLE("1234567890") },
     123        { RT_STR_TUPLE("<h2>asdfkjhasdflhj</h2>") },
     124        { RT_STR_TUPLE("<h2>asdfkjhasdflhj</h2>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") },
     125        { (const char *)g_abVBoxOrgMimeHtml1, sizeof(g_abVBoxOrgMimeHtml1) },
     126    };
     127
     128    for (size_t i = 0; i < RT_ELEMENTS(s_aRoundTrips); i++)
     129    {
     130        int      rc;
     131        char    *pszCfHtml = NULL;
     132        uint32_t cbCfHtml  = UINT32_MAX/2;
     133        rc = SharedClipboardWinConvertMIMEToCFHTML(s_aRoundTrips[i].psz, s_aRoundTrips[i].cch + 1, &pszCfHtml, &cbCfHtml);
     134        if (rc == VINF_SUCCESS)
     135        {
     136            if (strlen(pszCfHtml) + 1 != cbCfHtml)
     137                RTTestIFailed("#%u: SharedClipboardWinConvertMIMEToCFHTML(%s, %#zx,,) returned incorrect length: %#x, actual %#zx",
     138                              i, s_aRoundTrips[i].psz, s_aRoundTrips[i].cch, cbCfHtml, strlen(pszCfHtml) + 1);
     139
     140            char     *pszHtml = NULL;
     141            uint32_t  cbHtml  = UINT32_MAX/4;
     142            rc = SharedClipboardWinConvertCFHTMLToMIME(pszCfHtml, (uint32_t)strlen(pszCfHtml), &pszHtml, &cbHtml);
     143            if (rc == VINF_SUCCESS)
     144            {
     145                if (strlen(pszHtml) + 1 != cbHtml)
     146                    RTTestIFailed("#%u: SharedClipboardWinConvertCFHTMLToMIME(%s, %#zx,,) returned incorrect length: %#x, actual %#zx",
     147                                  i, pszHtml, strlen(pszHtml), cbHtml, strlen(pszHtml) + 1);
     148                if (strcmp(pszHtml, s_aRoundTrips[i].psz) != 0)
     149                    RTTestIFailed("#%u: roundtrip for '%s' LB %#zx failed, ended up with '%s'",
     150                                  i, s_aRoundTrips[i].psz, s_aRoundTrips[i].cch, pszHtml);
     151                RTMemFree(pszHtml);
     152            }
     153            else
     154                RTTestIFailed("#%u: SharedClipboardWinConvertCFHTMLToMIME(%s, %#zx,,) returned %Rrc, expected VINF_SUCCESS",
     155                              i, pszCfHtml, strlen(pszCfHtml), rc);
     156            RTMemFree(pszCfHtml);
     157        }
     158        else
     159            RTTestIFailed("#%u: SharedClipboardWinConvertMIMEToCFHTML(%s, %#zx,,) returned %Rrc, expected VINF_SUCCESS",
     160                          i, s_aRoundTrips[i].psz, s_aRoundTrips[i].cch, rc);
     161    }
     162}
     163
     164#endif /* RT_OS_WINDOWS */
     165
    79166
    80167int main(int argc, char *argv[])
     
    93180    RTTestBanner(hTest);
    94181
    95     /* Don't let assertions in the host service panic (core dump) the test cases. */
    96     RTAssertSetMayPanic(false);
    97 
    98182    /*
    99183     * Run the tests.
    100184     */
    101185    testAnnounceAndReadData();
     186#ifdef RT_OS_WINDOWS
     187    testHtmlCf();
     188#endif
    102189
    103190    /*
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