static SigV4Status_t parseQueryString()

in source/sigv4.c [1881:1947]


    static SigV4Status_t parseQueryString( const char * pQuery,
                                           size_t queryLen,
                                           size_t * pNumberOfParameters,
                                           CanonicalContext_t * pCanonicalRequest )
    {
        size_t currentParameter = 0U, i = 0U, startOfFieldOrValue = 0U;
        bool fieldHasValue = false;
        SigV4Status_t returnStatus = SigV4Success;

        assert( pNumberOfParameters != NULL );
        assert( pCanonicalRequest != NULL );
        assert( pCanonicalRequest->pQueryLoc != NULL );

        /* Note: Constness of the query string is casted out here, taking care not to modify
         * its contents in any way. */

        /* Set cursors to each field and value in the query string.
         * Note: We iterate the index to queryLen (instead of queryLen - 1) for the
         * special case of handling the last index as a terminating value of a query
         * parameter. */
        for( i = 0U; i <= queryLen; i++ )
        {
            /* This test is at the beginning of the loop to ensure that
             * `pCanonicalRequest->pQueryLoc`is only accessed with a valid index.
             * The final iteration may result in `currentParameter` holding
             * SIGV4_MAX_QUERY_PAIR_COUNT, in order to set the number of parameters. */
            if( currentParameter >= SIGV4_MAX_QUERY_PAIR_COUNT )
            {
                returnStatus = SigV4MaxQueryPairCountExceeded;
                LogError( ( "Failed to parse query string: Number of query parameters exceeds max threshold defined in config. "
                            "SIGV4_MAX_QUERY_PAIR_COUNT=%lu", ( unsigned long ) SIGV4_MAX_QUERY_PAIR_COUNT ) );
                break;
            }

            /* Encountering an '&' indicates the start of a new key, and the end of the
             * old value (or key if the field has no value). The last value will not be
             * followed by anything, so we iterate to one beyond the end of the string.
             * Short circuit evaluation ensures the string is not dereferenced for that case. */
            if( ( i == queryLen ) || ( pQuery[ i ] == '&' ) )
            {
                processAmpersandInQueryString( fieldHasValue, i, &startOfFieldOrValue,
                                               &currentParameter, pQuery, pCanonicalRequest );

                /* As '&' represents a new parameter, reset the flag about parameter value state.*/
                fieldHasValue = false;
            }
            else if( ( pQuery[ i ] == '=' ) && !fieldHasValue )
            {
                /* Store information about Query Parameter Key in the canonical context. This query parameter has an associated value. */
                setQueryParameterKey( currentParameter, &( pQuery[ startOfFieldOrValue ] ), i - startOfFieldOrValue, pCanonicalRequest );

                /* Set the starting index for the query parameter's value. */
                startOfFieldOrValue = i + 1U;

                /* Set the flag to indicate that the current parameter's value has been found. */
                fieldHasValue = true;
            }
            else
            {
                /* Empty else. */
            }
        }

        *pNumberOfParameters = currentParameter;

        return returnStatus;
    }