VirtualBox

Ignore:
Timestamp:
Apr 9, 2020 12:16:43 AM (5 years ago)
Author:
vboxsync
Message:

SharedClipboard: Refreshed readFromPasteboard() to prevent memory leaks and assumption of trailing zeros on strings. Also implemented HTML in the host->guest direction (disabled). bugref:9620

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedClipboard/darwin-pasteboard.cpp

    r83632 r83633  
    3030#include <iprt/utf16.h>
    3131
    32 #include "VBox/log.h"
    33 #include "VBox/HostServices/VBoxClipboardSvc.h"
    34 #include "VBox/GuestHost/SharedClipboard.h"
    35 #include "VBox/GuestHost/clipboard-helper.h"
     32#include <VBox/log.h>
     33#include <VBox/HostServices/VBoxClipboardSvc.h>
     34#include <VBox/GuestHost/SharedClipboard.h>
     35#include <VBox/GuestHost/clipboard-helper.h>
    3636
    3737
     
    3939*   Defined Constants And Macros                                                                                                 *
    4040*********************************************************************************************************************************/
     41/*#define WITH_HTML_H2G*/
     42
    4143/* For debugging */
    4244//#define SHOW_CLIPBOARD_CONTENT
     
    153155                            *pfFormats |= VBOX_SHCL_FMT_UNICODETEXT;
    154156                        }
     157#ifdef WITH_HTML_H2G
     158                        else if (UTTypeConformsTo(hStrFlavor, kUTTypeHTML))
     159                        {
     160                            Log(("queryNewPasteboardFormats: HTML flavor detected.\n"));
     161                            *pfFormats |= VBOX_SHCL_FMT_HTML;
     162                        }
     163#endif
    155164#ifdef LOG_ENABLED
    156165                        else if (LogIs2Enabled())
     
    200209    Log(("readFromPasteboard: fFormat = %02X\n", fFormat));
    201210
    202     OSStatus err = noErr;
    203 
    204211    /* Make sure all is in sync */
    205212    PasteboardSynchronize(pPasteboard);
    206213
    207214    /* Are some items in the pasteboard? */
    208     ItemCount itemCount;
    209     err = PasteboardGetItemCount(pPasteboard, &itemCount);
    210     if (itemCount < 1)
     215    ItemCount cItems;
     216    OSStatus orc = PasteboardGetItemCount(pPasteboard, &cItems);
     217    if (cItems < 1)
    211218        return VINF_SUCCESS;
    212219
    213     /* The id of the first element in the pasteboard */
     220    /*
     221     * Our default response...
     222     */
    214223    int rc = VERR_NOT_SUPPORTED;
    215     PasteboardItemID itemID;
    216     if (!(err = PasteboardGetItemIdentifier(pPasteboard, 1, &itemID)))
    217     {
    218         /* The guest request unicode */
     224
     225    /*
     226     * The id of the first element in the pasteboard
     227     */
     228    PasteboardItemID idItem;
     229    orc = PasteboardGetItemIdentifier(pPasteboard, 1, &idItem);
     230    if (orc == 0)
     231    {
     232        CFDataRef hDataCopy  = 0;
     233        size_t    cbDataCopy = 0;
     234
     235        /*
     236         * The guest request unicode
     237         */
    219238        if (fFormat & VBOX_SHCL_FMT_UNICODETEXT)
    220239        {
    221             CFDataRef outData;
    222             PRTUTF16 pwszTmp = NULL;
    223             /* Try utf-16 first */
    224             if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF16PlainText, &outData)))
    225             {
    226                 Log(("Clipboard content is utf-16\n"));
    227 
    228                 PRTUTF16 pwszString = (PRTUTF16)CFDataGetBytePtr(outData);
    229                 if (pwszString)
    230                     rc = RTUtf16DupEx(&pwszTmp, pwszString, 0);
    231                 else
    232                     rc = VERR_INVALID_PARAMETER;
    233             }
    234             /* Second try is utf-8 */
     240            PRTUTF16  pwszSrcFree = NULL;
     241            PCRTUTF16 pwszSrc     = NULL;
     242            size_t    cwcSrc      = 0;
     243
     244            /* First preference is plain UTF-16 text: */
     245            orc = PasteboardCopyItemFlavorData(pPasteboard, idItem, kUTTypeUTF16PlainText, &hDataCopy);
     246            if (orc == 0)
     247            {
     248                cbDataCopy = CFDataGetLength(hDataCopy);
     249                Log(("Clipboard content is utf-16 (%zu bytes)\n", cbDataCopy));
     250                pwszSrc = (PCRTUTF16)CFDataGetBytePtr(hDataCopy);
     251                if (pwszSrc)
     252                {
     253                    cwcSrc = RTUtf16NLen(pwszSrc, cbDataCopy / sizeof(RTUTF16));
     254                    if (cwcSrc >= cbDataCopy / sizeof(RTUTF16))
     255                    {
     256                        pwszSrcFree = RTUtf16Alloc((cwcSrc + 1) * sizeof(RTUTF16));
     257                        if (pwszSrcFree)
     258                        {
     259                            memcpy(pwszSrcFree, pwszSrc, cwcSrc * sizeof(RTUTF16));
     260                            pwszSrcFree[cwcSrc] = '\0';
     261                            pwszSrc = pwszSrcFree;
     262                        }
     263                        else
     264                        {
     265                            rc = VERR_NO_UTF16_MEMORY;
     266                            pwszSrc = NULL;
     267                        }
     268                    }
     269                }
     270                else
     271                    rc = VERR_GENERAL_FAILURE;
     272            }
     273            /* Second preference is plain UTF-8 text: */
    235274            else
    236                 if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF8PlainText, &outData)))
    237                 {
    238                     Log(("readFromPasteboard: clipboard content is utf-8\n"));
    239                     const char *pszString = (const char *)CFDataGetBytePtr(outData);
    240                     if (pszString)
    241                         rc = RTStrToUtf16(pszString, &pwszTmp);
     275            {
     276                orc = PasteboardCopyItemFlavorData(pPasteboard, idItem, kUTTypeUTF8PlainText, &hDataCopy);
     277                if (orc == 0)
     278                {
     279                    cbDataCopy = CFDataGetLength(hDataCopy);
     280                    Log(("readFromPasteboard: clipboard content is utf-8 (%zu bytes)\n", cbDataCopy));
     281                    const char *pszSrc = (const char *)CFDataGetBytePtr(hDataCopy);
     282                    if (pszSrc)
     283                    {
     284                        size_t cchSrc = RTStrNLen(pszSrc, cbDataCopy);
     285                        rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszSrcFree, 0, &cwcSrc);
     286                        if (RT_SUCCESS(rc))
     287                            pwszSrc = pwszSrcFree;
     288                    }
    242289                    else
    243                         rc = VERR_INVALID_PARAMETER;
    244                 }
    245             if (pwszTmp)
    246             {
    247                 /* Check how much longer will the converted text will be. */
    248                 size_t cwSrc = RTUtf16Len(pwszTmp);
    249                 size_t cwDest;
    250                 rc = ShClUtf16GetWinSize(pwszTmp, cwSrc, &cwDest);
    251                 if (RT_FAILURE(rc))
    252                 {
    253                     RTUtf16Free(pwszTmp);
    254                     Log(("readFromPasteboard: clipboard conversion failed.  vboxClipboardUtf16GetWinSize returned %Rrc.  Abandoning.\n", rc));
    255                     AssertRCReturn(rc, rc);
    256                 }
    257                 /* Set the actually needed data size */
    258                 *pcbActual = cwDest * 2;
    259                 /* Return success state */
    260                 rc = VINF_SUCCESS;
    261                 /* Do not copy data if the dst buffer is not big enough. */
    262                 if (*pcbActual <= cb)
    263                 {
    264                     rc = ShClUtf16LinToWin(pwszTmp, RTUtf16Len(pwszTmp), static_cast <PRTUTF16>(pv), cb / 2);
    265                     if (RT_FAILURE(rc))
    266                     {
    267                         RTUtf16Free(pwszTmp);
    268                         Log(("readFromPasteboard: clipboard conversion failed.  vboxClipboardUtf16LinToWin() returned %Rrc.  Abandoning.\n", rc));
    269                         AssertRCReturn(rc, rc);
    270                     }
     290                        rc = VERR_GENERAL_FAILURE;
     291                }
     292            }
     293            if (pwszSrc)
     294            {
     295                /*
     296                 * Convert to windows UTF-16.
     297                 */
     298                Assert(cwcSrc == RTUtf16Len(pwszSrc));
     299                size_t cwcDst = 0;
     300                rc = ShClUtf16GetWinSize(pwszSrc, cwcSrc, &cwcDst);
     301                if (RT_SUCCESS(rc))
     302                {
     303                    *pcbActual = cwcDst * sizeof(RTUTF16);
     304                    if (*pcbActual <= cb)
     305                    {
     306                        rc = ShClUtf16LinToWin(pwszSrc, cwcSrc, (PRTUTF16)pv, cb / sizeof(RTUTF16));
     307                        if (RT_SUCCESS(rc))
     308                        {
    271309#ifdef SHOW_CLIPBOARD_CONTENT
    272                     Log(("readFromPasteboard: clipboard content: %ls\n", static_cast <PRTUTF16>(pv)));
     310                            Log(("readFromPasteboard: clipboard content: %ls\n", (PCRTUTF16)pv));
    273311#endif
    274                 }
    275                 /* Free the temp string */
    276                 RTUtf16Free(pwszTmp);
    277             }
    278         }
    279         /* The guest request BITMAP */
     312                        }
     313                        else
     314                        {
     315                            Log(("readFromPasteboard: ShClUtf16LinToWin failed - %Rrc!\n", rc));
     316                            AssertRC(rc);
     317                        }
     318                    }
     319                    else
     320                    {
     321                        Log(("readFromPasteboard: Insufficient (text) buffer space: %#zx, need %#zx\n", cb, *pcbActual));
     322                        rc = VINF_SUCCESS;
     323                    }
     324                }
     325                else
     326                {
     327                    Log(("readFromPasteboard: ShClUtf16GetWinSize failed - %Rrc!\n", rc));
     328                    AssertRC(rc);
     329                }
     330                RTUtf16Free(pwszSrcFree);
     331            }
     332        }
     333        /*
     334         * The guest request BITMAP
     335         */
    280336        else if (fFormat & VBOX_SHCL_FMT_BITMAP)
    281337        {
    282             CFDataRef outData;
    283             const void *pTmp = NULL;
    284             size_t cbTmpSize;
    285             /* Get the data from the pasteboard */
    286             if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeBMP, &outData)))
    287             {
    288                 Log(("Clipboard content is BMP\n"));
    289                 pTmp = CFDataGetBytePtr(outData);
    290                 cbTmpSize = CFDataGetLength(outData);
    291             }
    292             if (pTmp)
    293             {
    294                 const void *pDib;
    295                 size_t cbDibSize;
    296                 rc = ShClBmpGetDib(pTmp, cbTmpSize, &pDib, &cbDibSize);
    297                 if (RT_FAILURE(rc))
    298                 {
    299                     rc = VERR_NOT_SUPPORTED;
    300                     Log(("readFromPasteboard: unknown bitmap format. vboxClipboardBmpGetDib returned %Rrc.  Abandoning.\n", rc));
    301                     AssertRCReturn(rc, rc);
    302                 }
    303 
    304                 *pcbActual = cbDibSize;
    305                 /* Return success state */
    306                 rc = VINF_SUCCESS;
    307                 /* Do not copy data if the dst buffer is not big enough. */
    308                 if (*pcbActual <= cb)
    309                 {
    310                     memcpy(pv, pDib, cbDibSize);
     338            /* Get the BMP data from the pasteboard */
     339            orc = PasteboardCopyItemFlavorData(pPasteboard, idItem, kUTTypeBMP, &hDataCopy);
     340            if (orc == 0)
     341            {
     342                cbDataCopy = CFDataGetLength(hDataCopy);
     343                Log(("Clipboard content is BMP (%zu bytes)\n", cbDataCopy));
     344                const void *pvSrc = CFDataGetBytePtr(hDataCopy);
     345                if (pvSrc)
     346                {
     347                    /*
     348                     * Try get the device independent bitmap (DIB) bit from it.
     349                     */
     350                    const void *pvDib;
     351                    size_t      cbDib;
     352                    rc = ShClBmpGetDib(pvSrc, cbDataCopy, &pvDib, &cbDib);
     353                    if (RT_SUCCESS(rc))
     354                    {
     355                        *pcbActual = cbDib;
     356                        if (*pcbActual <= cb)
     357                        {
     358                            memcpy(pv, pvDib, cbDib);
    311359#ifdef SHOW_CLIPBOARD_CONTENT
    312                     Log(("readFromPasteboard: clipboard content bitmap %d bytes\n", cbDibSize));
     360                            Log(("readFromPasteboard: clipboard content bitmap %zx bytes\n", cbDib));
    313361#endif
    314                 }
    315             }
    316         }
    317     }
    318 
    319     Log(("readFromPasteboard: rc = %02X\n", rc));
     362                        }
     363                        else
     364                            Log(("readFromPasteboard: Insufficient (bitmap) buffer space: %#zx, need %#zx\n", cb, cbDib));
     365                        rc = VINF_SUCCESS;
     366                    }
     367                    else
     368                    {
     369                        AssertRC(rc);
     370                        Log(("readFromPasteboard: ShClBmpGetDib failed - %Rrc - unknown bitmap format??\n", rc));
     371                        rc = VERR_NOT_SUPPORTED;
     372                    }
     373                }
     374                else
     375                    rc = VERR_GENERAL_FAILURE;
     376            }
     377            else
     378                LogFlow(("readFromPasteboard: PasteboardCopyItemFlavorData/kUTTypeBMP -> %d (%#x)\n", orc, orc));
     379        }
     380#ifdef WITH_HTML_H2G
     381        /*
     382         * The guest request HTML.  It expects a UTF-8 reply and we assume
     383         * that's what's on the pasteboard too.
     384         */
     385        else if (fFormat & VBOX_SHCL_FMT_HTML)
     386        {
     387            orc = PasteboardCopyItemFlavorData(pPasteboard, idItem, kUTTypeHTML, &hDataCopy);
     388            if (orc == 0)
     389            {
     390                cbDataCopy = CFDataGetLength(hDataCopy);
     391                Log(("Clipboard content is HTML (%zu bytes):\n", cbDataCopy));
     392                const char *pszSrc = (const char *)CFDataGetBytePtr(hDataCopy);
     393                if (pszSrc)
     394                {
     395                    Log3(("%.*Rhxd\n", cbDataCopy, pszSrc));
     396                    rc = RTStrValidateEncodingEx(pszSrc, cbDataCopy, 0 /*fFlags*/);
     397                    if (RT_SUCCESS(rc))
     398                    {
     399                        size_t cchSrc = RTStrNLen(pszSrc, cbDataCopy);
     400                        *pcbActual = cchSrc;
     401                        if (cchSrc <= cb)
     402                            memcpy(pv, pszSrc, cchSrc);
     403                        else
     404                            Log(("readFromPasteboard: Insufficient (HTML) buffer space: %#zx, need %#zx\n", cb, cchSrc));
     405                        rc = VINF_SUCCESS;
     406                    }
     407                    else
     408                    {
     409                        Log(("readFromPasteboard: Invalid UTF-8 encoding on pasteboard: %Rrc\n", rc));
     410                        rc = VERR_NOT_SUPPORTED;
     411                    }
     412                }
     413                else
     414                    rc = VERR_GENERAL_FAILURE;
     415            }
     416            else
     417                LogFlow(("readFromPasteboard: PasteboardCopyItemFlavorData/kUTTypeHTML -> %d (%#x)\n", orc, orc));
     418        }
     419#endif
     420        else
     421        {
     422            Log2(("readFromPasteboard: Unsupported format: %#x\n", fFormat));
     423            rc = VERR_NOT_SUPPORTED;
     424        }
     425
     426        /*
     427         * Release the data copy, if we got one.  There are no returns above!
     428         */
     429        if (hDataCopy)
     430            CFRelease(hDataCopy);
     431    }
     432    else
     433    {
     434        Log(("readFromPasteboard: PasteboardGetItemIdentifier failed: %u (%#x)\n", orc, orc));
     435        rc = VERR_NOT_SUPPORTED;
     436    }
     437
     438    Log(("readFromPasteboard: rc=%Rrc *pcbActual=%#zx\n", rc, *pcbActual));
    320439    return rc;
    321440}
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