VirtualBox

Changeset 77323 in vbox for trunk/src/VBox/Runtime/r3


Ignore:
Timestamp:
Feb 14, 2019 9:20:55 PM (6 years ago)
Author:
vboxsync
Message:

Runtime/serialport-win.cpp: Don't keep dwEventMask on the stack for overlapped I/O as this may get written to after the method returned corrupting stack memory. Fixes crashes on Windows

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/serialport-win.cpp

    r76553 r77323  
    7676    /** Events currently waited for. */
    7777    uint32_t            fEvtMask;
     78    /** Event mask as received by WaitCommEvent(). */
     79    DWORD               dwEventMask;
    7880    /** Flag whether a write is currently pending. */
    7981    bool                fWritePending;
     82    /** Event query pending. */
     83    bool                fEvtQueryPending;
    8084    /** Bounce buffer for writes. */
    8185    uint8_t            *pbBounceBuf;
     
    247251
    248252
     253/**
     254 * Processes the received Windows comm events and converts them to our format.
     255 *
     256 * @returns IPRT status code.
     257 * @param   pThis               The pipe instance handle.
     258 * @param   dwEventMask         Event mask received.
     259 * @param   pfEvtsRecv          Where to store the converted events.
     260 */
     261static int rtSerialPortEvtFlagsProcess(PRTSERIALPORTINTERNAL pThis, DWORD dwEventMask, uint32_t *pfEvtsRecv)
     262{
     263    int rc = VINF_SUCCESS;
     264
     265    if (dwEventMask & EV_RXCHAR)
     266        *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_RX;
     267    if (dwEventMask & EV_TXEMPTY)
     268    {
     269        if (pThis->fWritePending)
     270        {
     271            rc = rtSerialPortWriteCheckCompletion(pThis);
     272            if (rc == VINF_SUCCESS)
     273                *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_TX;
     274            else
     275                rc = VINF_SUCCESS;
     276        }
     277        else
     278            *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_TX;
     279    }
     280    if (dwEventMask & EV_BREAK)
     281        *pfEvtsRecv |= RTSERIALPORT_EVT_F_BREAK_DETECTED;
     282    if (dwEventMask & (EV_CTS | EV_DSR | EV_RING | EV_RLSD))
     283        *pfEvtsRecv |= RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED;
     284
     285    return rc;
     286}
     287
     288
     289/**
     290 * The internal comm event wait worker.
     291 *
     292 * @returns IPRT status code.
     293 * @param   pThis               The pipe instance handle.
     294 * @param   msTimeout           The timeout to wait for.
     295 */
     296static int rtSerialPortEvtWaitWorker(PRTSERIALPORTINTERNAL pThis, RTMSINTERVAL msTimeout)
     297{
     298    int rc = VINF_SUCCESS;
     299    HANDLE ahWait[2];
     300    ahWait[0] = pThis->hEvtDev;
     301    ahWait[1] = pThis->hEvtIntr;
     302
     303    DWORD dwRet = WaitForMultipleObjects(2, ahWait, FALSE, msTimeout == RT_INDEFINITE_WAIT ? INFINITE : msTimeout);
     304    if (dwRet == WAIT_TIMEOUT)
     305        rc = VERR_TIMEOUT;
     306    else if (dwRet == WAIT_FAILED)
     307        rc = RTErrConvertFromWin32(GetLastError());
     308    else if (dwRet == WAIT_OBJECT_0)
     309        rc = VINF_SUCCESS;
     310    else
     311    {
     312        Assert(dwRet == WAIT_OBJECT_0 + 1);
     313        rc = VERR_INTERRUPTED;
     314    }
     315
     316    return rc;
     317}
     318
     319
    249320RTDECL(int)  RTSerialPortOpen(PRTSERIALPORT phSerialPort, const char *pszPortAddress, uint32_t fFlags)
    250321{
     
    263334        pThis->fEvtMask         = 0;
    264335        pThis->fWritePending    = false;
     336        pThis->fEvtQueryPending = false;
    265337        pThis->pbBounceBuf      = NULL;
    266338        pThis->cbBounceBufUsed  = 0;
     
    786858    int rc = VINF_SUCCESS;
    787859    if (fEvtMask != pThis->fEvtMask)
     860    {
    788861        rc = rtSerialPortWinUpdateEvtMask(pThis, fEvtMask);
     862        if (   RT_SUCCESS(rc)
     863            && pThis->fEvtQueryPending)
     864        {
     865            /*
     866             * Setting a new event mask lets the WaitCommEvent() call finish immediately,
     867             * so clean up and process any events here.
     868             */
     869            rc = rtSerialPortEvtWaitWorker(pThis, 1);
     870            AssertRC(rc);
     871
     872            if (pThis->dwEventMask != 0)
     873            {
     874                pThis->fEvtQueryPending = false;
     875                return rtSerialPortEvtFlagsProcess(pThis, pThis->dwEventMask, pfEvtsRecv);
     876            }
     877        }
     878    }
    789879
    790880    /*
     
    817907    if (RT_SUCCESS(rc))
    818908    {
    819         DWORD dwEventMask = 0;
    820         HANDLE ahWait[2];
    821         ahWait[0] = pThis->hEvtDev;
    822         ahWait[1] = pThis->hEvtIntr;
    823 
    824         RT_ZERO(pThis->OverlappedEvt);
    825         pThis->OverlappedEvt.hEvent = pThis->hEvtDev;
    826 
    827         if (!WaitCommEvent(pThis->hDev, &dwEventMask, &pThis->OverlappedEvt))
    828         {
    829             DWORD dwRet = GetLastError();
    830             if (dwRet == ERROR_IO_PENDING)
    831             {
    832                 dwRet = WaitForMultipleObjects(2, ahWait, FALSE, msTimeout == RT_INDEFINITE_WAIT ? INFINITE : msTimeout);
    833                 if (dwRet == WAIT_TIMEOUT)
    834                     rc = VERR_TIMEOUT;
    835                 else if (dwRet == WAIT_FAILED)
     909        /* Set up a new event wait if there is none pending. */
     910        if (!pThis->fEvtQueryPending)
     911        {
     912            RT_ZERO(pThis->OverlappedEvt);
     913            pThis->OverlappedEvt.hEvent = pThis->hEvtDev;
     914
     915            pThis->dwEventMask = 0;
     916            pThis->fEvtQueryPending = true;
     917            if (!WaitCommEvent(pThis->hDev, &pThis->dwEventMask, &pThis->OverlappedEvt))
     918            {
     919                DWORD dwRet = GetLastError();
     920                if (dwRet == ERROR_IO_PENDING)
     921                    rc = VINF_SUCCESS;
     922                else
    836923                    rc = RTErrConvertFromWin32(GetLastError());
    837                 else if (dwRet != WAIT_OBJECT_0)
    838                     rc = VERR_INTERRUPTED;
    839924            }
    840925            else
    841                 rc = RTErrConvertFromWin32(dwRet);
    842         }
     926                pThis->fEvtQueryPending = false;
     927        }
     928
     929        Assert(RT_FAILURE(rc) || pThis->fEvtQueryPending);
     930
     931        if (   RT_SUCCESS(rc)
     932            || pThis->fEvtQueryPending)
     933            rc = rtSerialPortEvtWaitWorker(pThis, msTimeout);
    843934
    844935        if (RT_SUCCESS(rc))
    845936        {
    846             /* Check the event */
    847             if (dwEventMask & EV_RXCHAR)
    848                 *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_RX;
    849             if (dwEventMask & EV_TXEMPTY)
    850             {
    851                 if (pThis->fWritePending)
    852                 {
    853                     rc = rtSerialPortWriteCheckCompletion(pThis);
    854                     if (rc == VINF_SUCCESS)
    855                         *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_TX;
    856                     else
    857                         rc = VINF_SUCCESS;
    858                 }
    859                 else
    860                     *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_TX;
    861             }
    862             if (dwEventMask & EV_BREAK)
    863                 *pfEvtsRecv |= RTSERIALPORT_EVT_F_BREAK_DETECTED;
    864             if (dwEventMask & (EV_CTS | EV_DSR | EV_RING | EV_RLSD))
    865                 *pfEvtsRecv |= RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED;
     937            pThis->fEvtQueryPending = false;
     938            rc = rtSerialPortEvtFlagsProcess(pThis, pThis->dwEventMask, pfEvtsRecv);
    866939        }
    867940    }
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