VirtualBox

Changeset 13355 in vbox for trunk/src


Ignore:
Timestamp:
Oct 16, 2008 6:38:52 PM (16 years ago)
Author:
vboxsync
Message:

VBoxGuestR3LibGuestProp: AsserPtr should return on failure not crash on the next line. Made the timestamp convertion strict. Made all the enum output pointers optional. Fixed VERR_NO_DATA.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestProp.cpp

    r13291 r13355  
    272272                                    uint32_t *pcbBufActual)
    273273{
     274    /*
     275     * Create the GET_PROP message and call the host.
     276     */
    274277    GetProperty Msg;
    275278
     
    278281    Msg.hdr.u32Function = GET_PROP;
    279282    Msg.hdr.cParms = 4;
    280     VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName),
    281                        strlen(pszName) + 1);
     283    VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName), strlen(pszName) + 1);
    282284    VbglHGCMParmPtrSet(&Msg.buffer, pvBuf, cbBuf);
    283285    VbglHGCMParmUInt64Set(&Msg.timestamp, 0);
     
    287289    if (RT_SUCCESS(rc))
    288290        rc = Msg.hdr.result;
    289     if ((VERR_BUFFER_OVERFLOW == rc) && (pcbBufActual != NULL))
     291
     292    /*
     293     * The cbBufActual parameter is also returned on overflow so the call can
     294     * adjust his/her buffer.
     295     */
     296    if (    rc == VERR_BUFFER_OVERFLOW
     297        ||  pcbBufActual != NULL)
    290298    {
    291299        int rc2 = VbglHGCMParmUInt32Get(&Msg.size, pcbBufActual);
    292         if (!RT_SUCCESS(rc2))
    293             rc = rc2;
    294     }
    295     if (RT_SUCCESS(rc) && (pu64Timestamp != NULL))
     300        AssertRCReturn(rc2, RT_FAILURE(rc) ? rc : rc2);
     301    }
     302    if (RT_FAILURE(rc))
     303        return rc;
     304
     305    /*
     306     * Buffer layout: Value\0Flags\0.
     307     *
     308     * If the caller cares about any of these strings, make sure things are
     309     * propertly terminated (paranoia).
     310     */
     311    if (    RT_SUCCESS(rc)
     312        &&  (ppszValue != NULL || ppszFlags != NULL))
     313    {
     314        /* Validate / skip 'Name'. */
     315        char *pszFlags = (char *)memchr(pvBuf, '\0', cbBuf) + 1;
     316        AssertPtrReturn(pszFlags, VERR_TOO_MUCH_DATA);
     317        if (ppszValue)
     318            *ppszValue = (char *)pvBuf;
     319
     320        if (ppszFlags)
     321        {
     322            /* Validate 'Flags'. */
     323            void *pvEos = memchr(pszFlags, '\0', cbBuf - (pszFlags - (char *)pvBuf));
     324            AssertPtrReturn(pvEos, VERR_TOO_MUCH_DATA);
     325            *ppszFlags = pszFlags;
     326        }
     327    }
     328
     329    /* And the timestamp, if requested. */
     330    if (pu64Timestamp != NULL)
     331    {
    296332        rc = VbglHGCMParmUInt64Get(&Msg.timestamp, pu64Timestamp);
    297     if (RT_SUCCESS(rc) && (ppszValue != NULL))
    298         *ppszValue = reinterpret_cast<char *>(pvBuf);
    299     if (RT_SUCCESS(rc) && (ppszFlags != NULL))
    300     {
    301         char *pszEos = reinterpret_cast<char *>(memchr(pvBuf, '\0', cbBuf));
    302         if (pszEos)
    303             *ppszFlags = pszEos + 1;
    304         else
    305             rc = VERR_TOO_MUCH_DATA;
    306     }
    307     return rc;
     333        AssertRCReturn(rc, rc);
     334    }
     335
     336    return VINF_SUCCESS;
    308337}
    309338
     
    517546 *                          VbglR3GuestPropEnumFree when it is no longer needed.
    518547 * @param   ppszName        Where to store the first property name on success.
    519  *                          Should not be freed.
     548 *                          Should not be freed. Optional.
    520549 * @param   ppszValue       Where to store the first property value on success.
    521  *                          Should not be freed.
     550 *                          Should not be freed. Optional.
    522551 * @param   ppszValue       Where to store the first timestamp value on success.
     552 *                          Optional.
    523553 * @param   ppszFlags       Where to store the first flags value on success.
    524  *                          Should not be freed.
     554 *                          Should not be freed. Optional.
    525555 */
    526556VBGLR3DECL(int) VbglR3GuestPropEnum(uint32_t u32ClientId,
     
    533563                                    char const **ppszFlags)
    534564{
    535     int rc = VINF_SUCCESS;
     565    /* Create the handle. */
    536566    RTMemAutoPtr<VBGLR3GUESTPROPENUM, VbglR3GuestPropEnumFree> Handle;
    537567    Handle = (PVBGLR3GUESTPROPENUM)RTMemAllocZ(sizeof(VBGLR3GUESTPROPENUM));
    538568    if (!Handle)
    539         rc = VERR_NO_MEMORY;
     569        return VERR_NO_MEMORY;
    540570
    541571    /* Get the length of the pattern string, including the final terminator. */
     
    560590    uint32_t cchBuf = 4096;
    561591    RTMemAutoPtr<char> Buf;
     592
    562593    /* In reading the guest property data we are racing against the host
    563594     * adding more of it, so loop a few times and retry on overflow. */
    564     bool finish = false;
     595    int rc = VINF_SUCCESS;
     596    for (int i = 0; i < 10; ++i)
     597    {
     598        if (!Buf.realloc(cchBuf))
     599        {
     600            rc = VERR_NO_MEMORY;
     601            break;
     602        }
     603        rc = VbglR3GuestPropEnumRaw(u32ClientId, Patterns.get(),
     604                                    Buf.get(), cchBuf, &cchBuf);
     605        if (rc != VERR_BUFFER_OVERFLOW)
     606            break;
     607        cchBuf += 4096;  /* Just to increase our chances */
     608    }
    565609    if (RT_SUCCESS(rc))
    566         for (int i = 0; (i < 10) && !finish; ++i)
    567         {
    568             if (!Buf.realloc(cchBuf))
    569                 rc = VERR_NO_MEMORY;
    570             if (RT_SUCCESS(rc) || (VERR_BUFFER_OVERFLOW == rc))
    571                 rc = VbglR3GuestPropEnumRaw(u32ClientId, Patterns.get(),
    572                                             Buf.get(), cchBuf, &cchBuf);
    573             if (rc != VERR_BUFFER_OVERFLOW)
    574                 finish = true;
    575             else
    576                 cchBuf += 4096;  /* Just to increase our chances */
    577         }
    578     if (VERR_BUFFER_OVERFLOW == rc)
    579         rc = VERR_TOO_MUCH_DATA;
    580     if (RT_SUCCESS(rc))
    581     {
    582         /* Transfer ownership of the buffer to the handle structure. */
     610    {
     611        /*
     612         * Transfer ownership of the buffer to the handle structure and
     613         * call VbglR3GuestPropEnumNext to retriev the first entry.
     614         */
    583615        Handle->pchNext = Handle->pchBuf = Buf.release();
    584616        Handle->pchBufEnd = Handle->pchBuf + cchBuf;
    585     }
    586     if (RT_SUCCESS(rc))
     617
     618        const char *pszNameTmp;
     619        if (!ppszName)
     620            ppszName = &pszNameTmp;
    587621        rc = VbglR3GuestPropEnumNext(Handle.get(), ppszName, ppszValue,
    588622                                     pu64Timestamp, ppszFlags);
    589     if (RT_SUCCESS(rc) && (NULL == ppszName))
    590         /* No matching properties found */
    591         rc = VERR_NOT_FOUND;
    592     /* And transfer ownership of the handle to the caller. */
    593     if (RT_SUCCESS(rc))
    594         *ppHandle = Handle.release();
    595     return rc;
    596 }
    597 
    598 
    599 /**
    600  * Get the next guest property.  See @a VbglR3GuestPropEnum.
     623        if (RT_SUCCESS(rc) && *ppszName != NULL)
     624            *ppHandle = Handle.release();
     625        else if (RT_SUCCESS(rc))
     626            rc = VERR_NOT_FOUND; /* No matching properties found. */
     627    }
     628    else if (rc == VERR_BUFFER_OVERFLOW)
     629        rc = VERR_TOO_MUCH_DATA;
     630    return rc;
     631}
     632
     633
     634/**
     635 * Get the next guest property.
     636 *
     637 * See @a VbglR3GuestPropEnum.
    601638 *
    602639 * @returns VBox status code.
     
    605642 * @param  ppszName      Where to store the next property name.  This will be
    606643 *                       set to NULL if there are no more properties to
    607  *                       enumerate.  This pointer should not be freed.
     644 *                       enumerate.  This pointer should not be freed. Optional.
    608645 * @param  ppszValue     Where to store the next property value.  This will be
    609646 *                       set to NULL if there are no more properties to
    610  *                       enumerate.  This pointer should not be freed.
     647 *                       enumerate.  This pointer should not be freed. Optional.
    611648 * @param  pu64Timestamp Where to store the next property timestamp.  This
    612649 *                       will be set to zero if there are no more properties
    613  *                       to enumerate.
     650 *                       to enumerate. Optional.
    614651 * @param  ppszFlags     Where to store the next property flags.  This will be
    615652 *                       set to NULL if there are no more properties to
    616  *                       enumerate.  This pointer should not be freed.
     653 *                       enumerate.  This pointer should not be freed. Optional.
     654 *
     655 * @remarks While all output parameters are optional, you need at least one to
     656 *          figure out when to stop.
    617657 */
    618658VBGLR3DECL(int) VbglR3GuestPropEnumNext(PVBGLR3GUESTPROPENUM pHandle,
     
    622662                                        char const **ppszFlags)
    623663{
    624     /* The VBGLR3GUESTPROPENUM structure contains a buffer containing the raw
     664    /*
     665     * The VBGLR3GUESTPROPENUM structure contains a buffer containing the raw
    625666     * properties data and a pointer into the buffer which tracks how far we
    626667     * have parsed so far.  The buffer contains packed strings in groups of
     
    628669     * terminated by four empty strings.  We can rely on this layout unless
    629670     * the caller has been poking about in the structure internals, in which
    630      * case they must take responsibility for the results. */
    631 
    632     /* Get the pointer into the buffer to the next entry. */
    633     char *pchNext = pHandle->pchNext;
    634     /* And the pointer to the end of the buffer. */
    635     char *pchLast = pHandle->pchBufEnd;
    636     /* The index will initially point to the next name entry. */
    637     char *pszName = pchNext;
    638     /* The value for this property starts after the terminator for the name. */
    639     char *pszValue = pchNext = (char *)memchr(pchNext, '\0', pchLast - pchNext) + 1;
    640     AssertPtr(pchNext);  /* 0x1 is also an invalid pointer :) */
    641     /* The timestamp after the value... */
    642     char *pszTimestamp = pchNext = (char *)memchr(pchNext, '\0', pchLast - pchNext) + 1;
    643     AssertPtr(pchNext);
    644     /* ...and the flags after the timestamp. */
    645     char *pszFlags = pchNext = (char *)memchr(pchNext, '\0', pchLast - pchNext) + 1;
    646     AssertPtr(pchNext);
    647     uint64_t u64Timestamp = RTStrToUInt64(pszTimestamp);
    648     /* Only move the index pointer in the structure if we found a non-empty entry. */
     671     * case they must take responsibility for the results.
     672     *
     673     * Layout:
     674     *   Name\0Value\0Timestamp\0Flags\0
     675     */
     676    char *pchNext = pHandle->pchNext;       /* The cursor. */
     677    char *pchEnd  = pHandle->pchBufEnd;     /* End of buffer, for size calculations. */
     678
     679    char *pszName      = pchNext;
     680    char *pszValue     = pchNext = (char *)memchr(pchNext, '\0', pchEnd - pchNext) + 1;
     681    AssertPtrReturn(pchNext, VERR_PARSE_ERROR);  /* 0x1 is also an invalid pointer :) */
     682
     683    char *pszTimestamp = pchNext = (char *)memchr(pchNext, '\0', pchEnd - pchNext) + 1;
     684    AssertPtrReturn(pchNext, VERR_PARSE_ERROR);
     685
     686    char *pszFlags     = pchNext = (char *)memchr(pchNext, '\0', pchEnd - pchNext) + 1;
     687    AssertPtrReturn(pchNext, VERR_PARSE_ERROR);
     688
     689    /*
     690     * Don't move the index pointer if we found the terminating "\0\0\0\0" entry.
     691     * Don't try convert the timestamp either.
     692     */
     693    uint64_t u64Timestamp;
    649694    if (*pszName != '\0')
    650695    {
    651         pHandle->pchNext = pchNext = (char *)memchr(pchNext, '\0', pchLast - pchNext) + 1;
     696        pchNext = (char *)memchr(pchNext, '\0', pchEnd - pchNext) + 1;
     697        AssertPtrReturn(pchNext, VERR_PARSE_ERROR);
     698
     699        /* Convert the timestamp string into a number. */
     700        int rc = RTStrToUInt64Full(pszTimestamp, 0, &u64Timestamp);
     701        AssertRCSuccessReturn(rc, VERR_PARSE_ERROR);
     702
     703        pHandle->pchNext = pchNext;
    652704        AssertPtr(pchNext);
    653705    }
    654     /* And make sure that the buffer terminator is correct. */
    655     Assert(   (*pszName != '\0')
    656            || (('\0' == *pszValue) && ('\0' == *pszTimestamp) && ('\0' == *pszFlags))
    657           );
    658     *ppszName = *pszName != '\0' ? pszName : NULL;
    659     *ppszValue = *pszValue != '\0' ? pszValue : NULL;
    660     *pu64Timestamp = u64Timestamp;
    661     *ppszFlags = *pszFlags != '\0' ? pszFlags : NULL;
     706    else
     707    {
     708        u64Timestamp = 0;
     709        AssertMsgReturn(!*pszValue && !*pszTimestamp && !*pszFlags,
     710                        ("'%s' '%s' '%s'\n", pszValue, pszTimestamp, pszFlags),
     711                        VERR_PARSE_ERROR);
     712    }
     713
     714    /*
     715     * Everything is fine, set the return values.
     716     */
     717    if (ppszName)
     718        *ppszName  = *pszName  != '\0' ? pszName  : NULL;
     719    if (ppszValue)
     720        *ppszValue = *pszValue != '\0' ? pszValue : NULL;
     721    if (pu64Timestamp)
     722        *pu64Timestamp = u64Timestamp;
     723    if (ppszFlags)
     724        *ppszFlags = *pszFlags != '\0' ? pszFlags : NULL;
    662725    return VINF_SUCCESS;
    663726}
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