Example #1
0
/**
 * NAME
 *    strtolowercase_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strlolowercase_s(char *dest, rsize_t dmax)
 *
 * DESCRIPTION
 *    Scans the string converting uppercase characters to
 *    lowercase, leaving all other characters unchanged.
 *    The scanning stops at the first null or after dmax
 *    characters.
 *
 * Extenstion to:
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest       pointer to string
 *
 *    dmax       maximum length of string
 *
 * OUTPUT PARAMETERS
 *    dest       updated string
 *
 * RUNTIME CONSTRAINTS
 *    dest shall not be a null pointer.
 *    dmax shall not equal zero.
 *    dmax shall not be greater than RSIZE_MAX_STR.
 *
 * RETURN VALUE
 *    EOK        successful operation
 *    ESNULLP    NULL pointer
 *    ESZEROL    zero length
 *    ESLEMAX    length exceeds max limit
 *
 * ALSO SEE
 *    strtouppercase_s()
 *
 */
errno_t
strtolowercase_s (char *dest, rsize_t dmax)
{
    if (!dest) {
        invoke_safe_str_constraint_handler("strtolowercase_s: "
                   "dest is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("strtolowercase_s: "
                   "dmax is 0",
                   NULL, ESZEROL);
        return (ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strtolowercase_s: "
                   "dmax exceeds max",
                   NULL, ESLEMAX);
        return (ESLEMAX);
    }

    while (*dest && dmax) {

        if ( (*dest >= 'A') && (*dest <= 'Z')) {
              *dest = (char)(*dest + (char)32);
        }
        dest++;
        dmax--;
    }

    return (EOK);
}
Example #2
0
/**
 * NAME
 *    strnterminate_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    rsize_t
 *    strnterminate_s(char *dest, rsize_t dmax)
 *
 * DESCRIPTION
 *    The strnterminate_s function will terminate the string if a
 *    null is not encountered before dmax characters.
 *
 * EXTENSION TO
 *    ISO/IEC TR 24731-1, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest - pointer to string
 *
 *    dmax - restricted maximum length
 *
 * OUTPUT PARAMETERS
 *    dest - dest is terminated if needed
 *
 * RUNTIME CONSTRAINTS
 *    dest shall not be a null pointer
 *    dmax shall not be greater than RSIZE_MAX_STR
 *    dmax shall not equal zero
 *
 * RETURN VALUE
 *    The function returns a terminated string.  If a null is not
 *    encountered prior to dmax characters, the dmax character is
 *    set to null terminating the string. The string length is
 *    also returned.
 *
 * ALSO SEE
 *    strnlen_s()
 *
 */
rsize_t
strnterminate_s (char *dest, rsize_t dmax)
{
    rsize_t count;

    if (dest == NULL) {
        return (0);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("strnterminate_s: dmax is 0",
                   NULL, ESZEROL);
        return (0);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strnterminate_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return (0);
    }

    count = 0;
    while (dmax > 1) {
        if (*dest) {
            count++;
            dmax--;
            dest++;
        } else {
            break;
        }
    }
    *dest = '\0';

    return (count);
}
Example #3
0
/**
 * NAME
 *    strnlen_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    rsize_t
 *    strnlen_s(const char *dest, rsize_t dmax)
 *
 * DESCRIPTION
 *    The strnlen_s function computes the length of the string pointed
 *    to by dest.
 *
 * SPECIFIED IN
 *    ISO/IEC TR 24731-1, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest      pointer to string
 *
 *    dmax      restricted maximum length.
 *
 * OUTPUT PARAMETERS
 *    none
 *
 * RUNTIME CONSTRAINTS
 *    dest shall not be a null pointer
 *    dmax shall not be greater than RSIZE_MAX_STR
 *    dmax shall not equal zero
 *
 * RETURN VALUE
 *    The function returns the string length, excluding  the terminating
 *    null character.  If dest is NULL, then strnlen_s returns 0.
 *
 *    Otherwise, the strnlen_s function returns the number of characters
 *    that precede the terminating null character. If there is no null
 *    character in the first dmax characters of dest then strnlen_s returns
 *    dmax. At most the first dmax characters of dest are accessed
 *    by strnlen_s.
 *
 * ALSO SEE
 *    strnterminate_s()
 *
 */
rsize_t
strnlen_s (const char *dest, rsize_t dmax)
{
    rsize_t count;

    if (dest == NULL) {
        return RCNEGATE(0);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("strnlen_s: dmax is 0",
                   NULL, ESZEROL);
        return RCNEGATE(0);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strnlen_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return RCNEGATE(0);
    }

    count = 0;
    while (*dest && dmax) {
        count++;
        dmax--;
        dest++;
    }

    return RCNEGATE(count);
}
Example #4
0
/**
 * NAME
 *    strfirstsame_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strfirstsame_s(const char *dest, rsize_t dmax,
 *                   const char *src,  rsize_t *index)
 *
 * DESCRIPTION
 *    Returns the index of the first character that is the
 *    same between dest and src.  The scanning stops at the
 *    fisrt null in dest or src, or after dmax characters.
 *
 * EXTENSION TO
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest     pointer to string to compare against
 *
 *    dmax     restricted maximum length of string dest
 *
 *    src      pointer to the string to be compared to dest
 *
 *    index    pointer to returned index
 *
 * OUTPUT PARAMETERS
 *    index    updated index
 *
 * RUNTIME CONSTRAINTS
 *    Neither dest nor src shall be a null pointer.
 *    indicator shall not be a null pointer.
 *    dmax shall not be 0
 *    dmax shall not be greater than RSIZE_MAX_STR
 *
 * RETURN VALUE
 *    index to first same char, when the return code is OK
 *
 *    EOK         index to first same char is returned
 *    ESNULLP     NULL pointer
 *    ESZEROL     zero length
 *    ESLEMAX     length exceeds max limit
 *    ESNOTFND    not found
 *
 * ALSO SEE
 *    strfirstchar_s(), strfirstdiff_s(), strlastchar_s(),
 *    strlastdiff_s(), strlastsame_s()
 *
 */
errno_t
strfirstsame_s (const char *dest, rsize_t dmax,
                const char *src,  rsize_t *index)
{
    const char *rp = 0;

    if (index == NULL) {
        invoke_safe_str_constraint_handler("strfirstsame_s: index is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }
    *index = 0;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("strfirstsame_s: dest is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }

    if (src == NULL) {
        invoke_safe_str_constraint_handler("strfirstsame_s: src is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }

    if (dmax == 0 ) {
        invoke_safe_str_constraint_handler("strfirstsame_s: dmax is 0",
                   NULL, ESZEROL);
        return (ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strfirstsame_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return (ESLEMAX);
    }

    /* hold reference point */
    rp = dest;

    /*
     * find the offset
     */
    while (*dest && *src && dmax) {

        if (*dest == *src) {
            *index = (uint32_t)(dest - rp);
            return (EOK);
        }

        dest++;
        src++;
        dmax--;
    }

    return (ESNOTFND);
}
Example #5
0
/**
 * NAME
 *    strfirstdiff_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strfirstdiff_s(const char *dest, rsize_t dmax,
 *                   const char *src, rsize_t *index)
 *
 * DESCRIPTION
 *    Returns the index of the first character that is different
 *    between dest and src. Index is valid only for OK.
 *    The scanning stops at the first null in dest or src, or
 *    after dmax characters.
 *
 * EXTENSION TO
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest     pointer to string to compare against
 *
 *    dmax     restricted maximum length of string dest
 *
 *    src      pointer to the string to be compared to dest
 *
 *    index    pointer to returned index to first difference
 *
 * OUTPUT PARAMETERS
 *    index    returned index to first difference
 *
 * RUNTIME CONSTRAINTS
 *    Neither dest nor src shall be a null pointer.
 *    indicator shall not be a null pointer.
 *    dmax shall not be 0.
 *    dmax shall not be greater than RSIZE_MAX_STR.
 *
 * RETURN VALUE
 *    index to first difference, when the return code is OK
 *
 *    EOK         index to first diff is returned
 *    ESNODIFF    no difference
 *    ESNULLP     NULL pointer
 *    ESZEROL     zero length
 *    ESLEMAX     length exceeds max limit
 *
 * ALSO SEE
 *    strfirstchar_s(), strfirstsame_s(), strlastchar_s(),
 *    strlastdiff_s(), strlastsame_s()
 *
 */
 errno_t
 strfirstdiff_s (const char *dest, rsize_t dmax,
                 const char *src, rsize_t *index)
{
    const char *rp;

    if (index == NULL) {
        invoke_safe_str_constraint_handler("strfirstdiff_s: index is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }
    *index = 0;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("strfirstdiff_s: dest is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }

    if (src == NULL) {
        invoke_safe_str_constraint_handler("strfirstdiff_s: src is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }

    if (dmax == 0 ) {
        invoke_safe_str_constraint_handler("strfirstdiff_s: dmax is 0",
                   NULL, ESZEROL);
        return (ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strfirstdiff_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return (ESLEMAX);
    }

    /* hold reference point */
    rp = dest;

    while (*dest && *src && dmax) {

        if (*dest != *src) {
            *index = dest - rp;
            return (EOK);
        }
        dmax--;
        dest++;
        src++;
    }

    return (ESNODIFF);
}
Example #6
0
/**
 * NAME
 *    strcmpfld_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strcmpfld_s(const char *dest, rsize_t dmax,
 *                const char *src, int *indicator)
 *
 * DESCRIPTION
 *    Compares the character array pointed to by src to the character array
 *    pointed to by dest for dmax characters.  The null terminator does not
 *    stop the comparison.
 *
 * EXTENSION TO
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest       pointer to character array to compare against
 *
 *    dmax       restricted maximum length of dest.  The length is
 *                used for the comparison of src against dest.
 *
 *    src        pointer to the character array to be compared to dest
 *
 *    indicator  pointer to result indicator, greater than, equal
 *               to or less than 0, if the character array pointed
 *                to by dest is greater than, equal to or less
 *                than the character array pointed to by src.
 * OUTPUT
 *    indicator  updated result indicator
 *
 * RUNTIME CONSTRAINTS
 *    Neither dest nor src shall be a null pointer.
 *    indicator shall not be a null pointer.
 *    dmax shall not be 0
 *    dmax shall not be greater than RSIZE_MAX_STR
 *
 * RETURN VALUE
 *    indicator, when the return code is OK
 *        >0   dest greater than src
 *         0   strings the same
 *        <0   dest less than src
 *
 *    EOK
 *    ESNULLP     pointer was null
 *    ESZEROL     length was zero
 *    ESLEMAX     length exceeded max
 *
 * ALSO SEE
 *    strcpyfld_s(), strcpyfldin_s(), strcpyfldout_s()
 *
 */
errno_t
strcmpfld_s (const char *dest, rsize_t dmax,
             const char *src, int *indicator)
{
    if (indicator == NULL) {
        invoke_safe_str_constraint_handler("strcmpfld_s: indicator is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }
    *indicator = 0;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("strcmpfld_s: dest is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }

    if (src == NULL) {
        invoke_safe_str_constraint_handler("strcmpfld_s: src is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("strcmpfld_s: dmax is 0",
                   NULL, ESZEROL);
        return (ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strcmpfld_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return (ESLEMAX);
    }

    /* compare for dmax charactrers, not the null! */
    while (dmax) {

        if (*dest != *src) {
            break;
        }

        dest++;
        src++;
        dmax--;
    }

    *indicator = *dest - *src;
    return (EOK);
}
Example #7
0
/**
 * NAME
 *    strishex_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    bool
 *    strishex_s(const char *dest, rsize_t dmax)
 *
 * DESCRIPTION
 *    This function checks that the entire string contains
 *    hex characters.  The scanning stops at the first null
 *    or after dmax characters.
 *
 * EXTENSION TO
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest       pointer to string
 *
 *    dmax       maximum length of string
 *
 * OUTPUT PARAMETERS
 *    none
 *
 * RUNTIME CONSTRAINTS
 *    dest shall not be a null pointer.
 *    dmax shall not equal zero.
 *    dmax shall not be greater than RSIZE_MAX_STR.
 *
 * RETURN VALUE
 *    true      string is hex
 *    false     string is not hex or an error occurred
 *
 * ALSO SEE
 *    strisalphanumeric_s(), strisascii_s(), strisdigit_s(),
 *    strislowercase_s(), strismixedcase_s(),
 *    strisuppercase_s()
 *
 */
bool
strishex_s (const char *dest, rsize_t dmax)
{
    if (!dest) {
        invoke_safe_str_constraint_handler("strishex_s: dest is null",
                   NULL, ESNULLP);
        return (false);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("strishex_s: dmax is 0",
                   NULL, ESZEROL);
        return (false);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strishex_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return (false);
    }

    if (*dest == '\0') {
        return (false);
    }

    while (*dest && dmax) {

        if (((*dest >= '0') && (*dest <= '9')) ||
            ((*dest >= 'a') && (*dest <= 'f')) ||
            ((*dest >= 'A') && (*dest <= 'F'))) {
            dest++;
            dmax--;

        } else {
            return (false);
        }
    }

    return (true);
}
Example #8
0
/**
 * NAME
 *    strisuppercase_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    bool
 *    strisuppercase_s(const char *dest, rsize_t dmax)
 *
 * DESCRIPTION
 *    This function checks if entire string is uppercase
 *    The scanning stops at the first null or after dmax
 *    characters.
 *
 * EXTENSION TO
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest      pointer to string
 *
 *    dmax      maximum length of string
 *
 * OUTPUT PARAMETERS
 *    none
 *
 * RUNTIME CONSTRAINTS
 *    dest shall not be a null pointer.
 *    dmax shall not equal zero.
 *    dmax shall not be greater than RSIZE_MAX_STR.
 *
 * RETURN VALUE
 *    true      string is uppercase
 *    false     string is not uppercase or an error occurred
 *
 * ALSO SEE
 *    strisalphanumeric_s(), strisascii_s(), strisdigit_s(),
 *    strishex_s(), strislowercase_s(), strismixedcase_s(),
 *
 */
bool
strisuppercase_s (const char *dest, rsize_t dmax)
{

    if (!dest) {
        invoke_safe_str_constraint_handler("strisuppercase_s: "
                   "dest is null",
                   NULL, ESNULLP);
        return (false);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("strisuppercase_s: "
                   "dmax is 0",
                   NULL, ESZEROL);
        return (false);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strisuppercase_s: "
                   "dmax exceeds max",
                   NULL, ESLEMAX);
        return (false);
    }

    if (*dest == '\0') {
        return (false);
    }

    while (*dest) {

        if ((*dest < 'A') || (*dest > 'Z')) {
            return (false);
        }
        dest++;
        dmax--;
    }

    return (true);
}
Example #9
0
/**
 * NAME
 *    strcpyfldin_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strcpyfldin_s(char *dest, rsize_t dmax,
 *                  const char *src, rsize_t slen)
 *
 * DESCRIPTION
 *    The strcpyfldin_s function copies at most slen characters from the
 *    null terminated string pointed to by src into the fixed character
 *    array pointed to by dest. The copy operation stops on the  null
 *    character if encountered and then continues to fill the field
 *    with nulls up to dmax characters.
 *
 * EXTENSION TO
 *    ISO/IEC TR 24731-1, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest      pointer to character array that will be replaced by src.
 *
 *    dmax      restricted maximum length of dest
 *
 *    src       pointer to the null terminated string that will be copied
 *               into the character array pointed to by dest
 *
 *    slen      length of source
 *
 * OUTPUT PARAMETERS
 *    dest      updated
 *
 * RUNTIME CONSTRAINTS
 *    Neither dest nor src shall be a null pointer.
 *    dmax shall not equal zero.
 *    dmax shall not be greater than RSIZE_MAX_STR.
 *    slen shall not equal zero.
 *    slen shall not exceed dmax
 *    Copying shall not take place between objects that overlap.
 *    If there is a runtime-constraint violation, then if dest
 *       is not a null pointer and dmax is greater than zero and
 *       not greater than RSIZE_MAX_STR, then strcpyfldin_s nulls dest.
 *
 * RETURN VALUE
 *    EOK        successful operation
 *    ESNULLP    NULL pointer
 *    ESZEROL    zero length
 *    ESLEMAX    length exceeds max limit
 *    ESOVRLP    strings overlap
 *
 * ALSO SEE
 *    strcpyfld_s(), strcpyfldout_s(),
 *
 */
errno_t
strcpyfldin_s (char *dest, rsize_t dmax, const char *src, rsize_t slen)
{
    rsize_t orig_dmax;
    char *orig_dest;
    const char *overlap_bumper;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("strcpyfldin_s: dest is null",
                                           NULL, ESNULLP);
        return (ESNULLP);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("strcpyfldin_s: dmax is 0",
                                           NULL, ESZEROL);
        return (ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strcpyfldin_s: dmax exceeds max",
                                           NULL, ESLEMAX);
        return (ESLEMAX);
    }

    if (src == NULL) {
        /* null string to clear data */
        while (dmax) {
            *dest = '\0';
            dmax--;
            dest++;
        }

        invoke_safe_str_constraint_handler("strcpyfldin_s: src is null",
                                           NULL, ESNULLP);
        return (ESNULLP);
    }

    if (slen == 0) {
        /* null string to clear data */
        while (dmax) {
            *dest = '\0';
            dmax--;
            dest++;
        }

        invoke_safe_str_constraint_handler("strcpyfldin_s: slen is 0",
                                           NULL, ESZEROL);
        return (ESZEROL);
    }

    if (slen > dmax) {
        /* null string to clear data */
        while (dmax) {
            *dest = '\0';
            dmax--;
            dest++;
        }

        invoke_safe_str_constraint_handler("strcpyfldin_s: slen exceeds max",
                                           NULL, ESLEMAX);
        return (ESLEMAX);
    }


    /* hold base of dest in case src was not copied */
    orig_dmax = dmax;
    orig_dest = dest;

    if (dest < src) {
        overlap_bumper = src;

        while (dmax > 0 && *src) {

            if (dest == overlap_bumper) {
                dmax = orig_dmax;
                dest = orig_dest;

                /* null string to eliminate partial copy */
                while (dmax) {
                    *dest = '\0';
                    dmax--;
                    dest++;
                }

                invoke_safe_str_constraint_handler(
                    "strcpyfldin_s: overlapping objects",
                    NULL, ESOVRLP);
                return (ESOVRLP);
            }

            dmax--;
            *dest++ = *src++;
        }

    } else {
        overlap_bumper = dest;

        while (dmax > 0 && *src) {

            if (src == overlap_bumper) {
                dmax = orig_dmax;
                dest = orig_dest;

                /* null string to eliminate partial copy */
                while (dmax) {
                    *dest = '\0';
                    dmax--;
                    dest++;
                }

                invoke_safe_str_constraint_handler(
                    "strcpyfldin_s: overlapping objects",
                    NULL, ESOVRLP);
                return (ESOVRLP);
            }

            dmax--;
            *dest++ = *src++;
        }
    }

    /*
     * finish filling in the field with nulls if there is slack space
     */
    while (dmax) {
        *dest = '\0';
        dmax--;
        dest++;
    }

    return (EOK);
}
Example #10
0
/*
 * NAME
 *    strncpy_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strncpy_s(char *dest, rsize_t dmax, const char *src, rsize_t slen)
 *
 * DESCRIPTION
 *    The strncpy_s function copies not more than slen successive characters
 *    (characters that follow a null character are not copied) from the
 *    array pointed to by src to the array pointed to by dest. If no null
 *    character was copied from src, then dest[n] is set to a null character.
 *
 *    All elements following the terminating null character (if any)
 *    written by strncpy_s in the array of dmax characters pointed to
 *    by dest take on the null value when strncpy_s returns.
 *
 * Specicified in:
 *    ISO/IEC TR 24731-1, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest      pointer to string that will be replaced by src.
 *              The resulting string is null terminated.
 *
 *    dmax      restricted maximum length of the resulting dest,
 *              including the null
 *
 *    src       pointer to the string that will be copied
 *              to string dest
 *
 *    slen      the maximum number of characters to copy from src
 *
 * OUTPUT PARAMETERS
 *    dest      updated with src string
 *
 * RUNTIME CONSTRAINTS
 *    Neither dmax nor slen shall be equal to zero.
 *    Neither dmax nor slen shall be equal zero.
 *    Neither dmax nor slen shall be greater than RSIZE_MAX_STR.
 *    If slen is either greater than or equal to dmax, then dmax
 *     should be more than strnlen_s(src,dmax)
 *    Copying shall not take place between objects that overlap.
 *    If there is a runtime-constraint violation, then if dest
 *       is not a null pointer and dmax greater than RSIZE_MAX_STR,
 *       then strncpy_s nulls dest.
 *
 * RETURN VALUE
 *    EOK        successful operation, the characters in src were copied
 *                  to dest and the result is null terminated.
 *    ESNULLP    NULL pointer
 *    ESZEROL    zero length
 *    ESLEMAX    length exceeds max limit
 *    ESOVRLP    strings overlap
 *    ESNOSPC    not enough space to copy src
 *
 * ALSO SEE
 *    strcat_s(), strncat_s(), strcpy_s()
 *-
 */
errno_t
strncpy_s (char *dest, rsize_t dmax, const char *src, rsize_t slen)
{
    rsize_t orig_dmax;
    char *orig_dest;
    const char *overlap_bumper;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("strncpy_s: dest is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("strncpy_s: dmax is 0",
                   NULL, ESZEROL);
        return RCNEGATE(ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strncpy_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return RCNEGATE(ESLEMAX);
    }

    /* hold base in case src was not copied */
    orig_dmax = dmax;
    orig_dest = dest;

    if (src == NULL) {
        handle_error(orig_dest, orig_dmax, "strncpy_s: "
                     "src is null",
                     ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (slen == 0) {
        handle_error(orig_dest, orig_dmax, "strncpy_s: "
                     "slen is zero",
                     ESZEROL);
        return RCNEGATE(ESZEROL);
    }

    if (slen > RSIZE_MAX_STR) {
        handle_error(orig_dest, orig_dmax, "strncpy_s: "
                     "slen exceeds max",
                     ESLEMAX);
        return RCNEGATE(ESLEMAX);
    }


   if (dest < src) {
       overlap_bumper = src;

        while (dmax > 0) {
            if (dest == overlap_bumper) {
                handle_error(orig_dest, orig_dmax, "strncpy_s: "
                        "overlapping objects",
                        ESOVRLP);
                return RCNEGATE(ESOVRLP);
            }

            if (slen == 0) {
                /*
                 * Copying truncated to slen chars.  Note that the TR says to
                 * copy slen chars plus the null char.  We null the slack.
                 */
#ifdef SAFECLIB_STR_NULL_SLACK
                while (dmax) { *dest = '\0'; dmax--; dest++; }
#else
                *dest = '\0';
#endif
                return RCNEGATE(EOK);
            }

            *dest = *src;
            if (*dest == '\0') {
#ifdef SAFECLIB_STR_NULL_SLACK
                /* null slack */
                while (dmax) { *dest = '\0'; dmax--; dest++; }
#endif
                return RCNEGATE(EOK);
            }

            dmax--;
            slen--;
            dest++;
            src++;
        }

    } else {
        overlap_bumper = dest;

        while (dmax > 0) {
            if (src == overlap_bumper) {
                handle_error(orig_dest, orig_dmax, "strncpy_s: "
                        "overlapping objects",
                        ESOVRLP);
                return RCNEGATE(ESOVRLP);
            }

            if (slen == 0) {
                /*
                 * Copying truncated to slen chars.  Note that the TR says to
                 * copy slen chars plus the null char.  We null the slack.
                 */
#ifdef SAFECLIB_STR_NULL_SLACK
                while (dmax) { *dest = '\0'; dmax--; dest++; }
#else
                *dest = '\0';
#endif
                return RCNEGATE(EOK);
            }

            *dest = *src;
            if (*dest == '\0') {
#ifdef SAFECLIB_STR_NULL_SLACK
                /* null slack */
                while (dmax) { *dest = '\0'; dmax--; dest++; }
#endif
                return RCNEGATE(EOK);
            }

            dmax--;
            slen--;
            dest++;
            src++;
        }
    }

    /*
     * the entire src was not copied, so zero the string
     */
    handle_error(orig_dest, orig_dmax, "strncpy_s: not enough "
                 "space for src",
                 ESNOSPC);
    return RCNEGATE(ESNOSPC);
}
Example #11
0
/**
 * NAME
 *    strspn_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strspn_s(const char *dest, rsize_t dmax,
 *             const char *src,  rsize_t slen, rsize_t *count)
 *
 * DESCRIPTION
 *    This function computes the prefix length of the string
 *    pointed to by dest which consists entirely of characters
 *    that are included from the string pointed to by src.
 *
 * EXTENSION TO
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest     pointer to string to determine the prefix
 *
 *    dmax     restricted maximum length of string dest
 *
 *    src      pointer to exclusion string
 *
 *    slen     restricted maximum length of string src
 *
 *    count    pointer to a count variable that will be updated
 *              with the dest substring length
 *
 * OUTPUT PARAMETERS
 *    count    updated count
 *
 * RUNTIME CONSTRAINTS
 *    Neither dest nor src shall be a null pointer.
 *    count shall not be a null pointer.
 *    dmax shall not be 0
 *    dmax shall not be greater than RSIZE_MAX_STR
 *
 * RETURN VALUE
 *    EOK         count
 *    ESNULLP     NULL pointer
 *    ESZEROL     zero length
 *    ESLEMAX     length exceeds max limit
 *
 * ALSO SEE
 *    strcspn_s(), strpbrk_s(), strstr_s(), strprefix_s()
 *
 */
errno_t
strspn_s (const char *dest, rsize_t dmax,
          const char *src,  rsize_t slen, rsize_t *count)
{
    const char *scan2;
    rsize_t smax;
    bool match_found;

    if (count== NULL) {
        invoke_safe_str_constraint_handler("strspn_s: count is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }
    *count = 0;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("strspn_s: dest is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (src == NULL) {
        invoke_safe_str_constraint_handler("strspn_s: src is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (dmax == 0 ) {
        invoke_safe_str_constraint_handler("strspn_s: dmax is 0",
                   NULL, ESZEROL);
        return RCNEGATE(ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strspn_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return RCNEGATE(ESLEMAX);
    }

    if (slen == 0 ) {
        invoke_safe_str_constraint_handler("strspn_s: slen is 0",
                   NULL, ESZEROL);
        return RCNEGATE(ESZEROL);
    }

    if (slen > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strspn_s: slen exceeds max",
                   NULL, ESLEMAX);
        return RCNEGATE(ESLEMAX);
    }

    while (*dest && dmax) {

        /*
         * Scan the entire src string for each dest character, counting
         * inclusions.
         */
        match_found = false;
        smax = slen;
        scan2 = src;
        while (*scan2 && smax) {

            if (*dest == *scan2) {
                match_found = true;
                break;
            }
            scan2++;
            smax--;
        }

        if (match_found) {
            (*count)++;
        } else {
            break;
        }

        dest++;
        dmax--;
    }

    return RCNEGATE(EOK);
}
Example #12
0
/**
 * NAME
 *    strpbrk_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strpbrk_s(char *dest, rsize_t dmax,
 *              char *src,  rsize_t slen, char **first)
 *
 * DESCRIPTION
 *    Returns a pointer, first, to the first ocurrence of any character
 *    in src which is contained in dest.
 *
 * EXTENSION TO
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest     pointer to string
 *
 *    dmax     restricted maximum length of string dest
 *
 *    src      pointer to string
 *
 *    slen     restricted length of string src
 *
 *    first    returned pointer to first occurence
 *
 * OUTPUT PARAMETERS
 *    none
 *
 * RUNTIME CONSTRAINTS
 *    Neither dest nor src shall be a null pointer.
 *    first shall not be a null pointer.
 *    dmax shall not be 0
 *    dmax shall not be greater than RSIZE_MAX_STR
 *
 * RETURN VALUE
 *    pointer to the first ocurrence of any character
 *    contained in src
 *
 *    EOK         count
 *    ESNULLP     NULL pointer
 *    ESZEROL     zero length
 *    ESLEMAX     length exceeds max limit
 *
 * ALSO SEE
 *    strfirstchar_s(), strlastchar_s(), strfirstdiff_s(),
 *    strfirstsame_s(), strlastdiff_s(), strlastsame_s()
 *
 */
errno_t
strpbrk_s (char *dest, rsize_t dmax,
           char *src,  rsize_t slen, char **first)
{
    char *ps;
    rsize_t len;

    if (first == NULL) {
        invoke_safe_str_constraint_handler("strpbrk_s: count is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }
    *first = NULL;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("strpbrk_s: dest is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (src == NULL) {
        invoke_safe_str_constraint_handler("strpbrk_s: src is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (dmax == 0 ) {
        invoke_safe_str_constraint_handler("strpbrk_s: dmax is 0",
                   NULL, ESZEROL);
        return RCNEGATE(ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strpbrk_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return RCNEGATE(ESLEMAX);
    }

    if (slen == 0 ) {
        invoke_safe_str_constraint_handler("strpbrk_s: slen is 0",
                   NULL, ESZEROL);
        return RCNEGATE(ESZEROL);
    }

    if (slen > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strpbrk_s: slen exceeds max",
                   NULL, ESLEMAX);
        return RCNEGATE(ESLEMAX);
    }

    /*
     * look for a matching char in the substring src
     */
    while (*dest && dmax) {

        ps = src;
        len = slen;
        while (*ps) {

            /* check for a match with the substring */
            if (*dest == *ps) {
                *first = dest;
                return RCNEGATE(EOK);
            }
            ps++;
            len--;
        }
        dest++;
        dmax--;
    }

    return RCNEGATE(ESNOTFND);
}
Example #13
0
/**
 * NAME
 *    strcpy_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strcpy_s(char *dest, rsize_t dmax, const char *src)
 *
 * DESCRIPTION
 *    The strcpy_s function copies the string pointed to by src
 *    (including the terminating null character) into the array
 *    pointed to by dest. All elements following the terminating
 *    null character (if any) written by strcpy_s in the array
 *    of dmax characters pointed to by dest are nulled when
 *    strcpy_s returns.
 *
 * SPECIFIED IN
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest      pointer to string that will be replaced by src.
 *
 *    dmax      restricted maximum length of dest
 *
 *    src       pointer to the string that will be copied
 *               to dest
 *
 * OUTPUT PARAMETERS
 *    dest      updated
 *
 * RUNTIME CONSTRAINTS
 *    Neither dest nor src shall be a null pointer.
 *    dmax shall not be greater than RSIZE_MAX_STR.
 *    dmax shall not equal zero.
 *    dmax shall be greater than strnlen_s(src, dmax).
 *    Copying shall not take place between objects that overlap.
 *    If there is a runtime-constraint violation, then if dest
 *       is not a null pointer and destmax is greater than zero and
 *       not greater than RSIZE_MAX_STR, then strcpy_s nulls dest.
 *
 * RETURN VALUE
 *    EOK        successful operation, the characters in src were
 *               copied into dest and the result is null terminated.
 *    ESNULLP    NULL pointer
 *    ESZEROL    zero length
 *    ESLEMAX    length exceeds max limit
 *    ESOVRLP    strings overlap
 *    ESNOSPC    not enough space to copy src
 *
 * ALSO SEE
 *    strcat_s(), strncat_s(), strncpy_s()
 *
 */
errno_t
strcpy_s (char *dest, rsize_t dmax, const char *src)
{
    rsize_t orig_dmax;
    char *orig_dest;
    const char *overlap_bumper;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("strcpy_s: dest is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("strcpy_s: dmax is 0",
                   NULL, ESZEROL);
        return RCNEGATE(ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strcpy_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return RCNEGATE(ESLEMAX);
    }

    if (src == NULL) {
#ifdef SAFECLIB_STR_NULL_SLACK
        /* null string to clear data */
        while (dmax) {  *dest = '\0'; dmax--; dest++; }
#else
        *dest = '\0';
#endif
        invoke_safe_str_constraint_handler("strcpy_s: src is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (dest == src) {
        return RCNEGATE(EOK);
    }

    /* hold base of dest in case src was not copied */
    orig_dmax = dmax;
    orig_dest = dest;

    if (dest < src) {
        overlap_bumper = src;

        while (dmax > 0) {
            if (dest == overlap_bumper) {
                handle_error(orig_dest, orig_dmax, "strcpy_s: "
                             "overlapping objects",
                             ESOVRLP);
                return RCNEGATE(ESOVRLP);
            }

            *dest = *src;
            if (*dest == '\0') {
#ifdef SAFECLIB_STR_NULL_SLACK
                /* null slack to clear any data */
                while (dmax) { *dest = '\0'; dmax--; dest++; }
#endif
                return RCNEGATE(EOK);
            }

            dmax--;
            dest++;
            src++;
        }

    } else {
        overlap_bumper = dest;

        while (dmax > 0) {
            if (src == overlap_bumper) {
                handle_error(orig_dest, orig_dmax, "strcpy_s: "
                      "overlapping objects",
                      ESOVRLP);
                return RCNEGATE(ESOVRLP);
            }

            *dest = *src;
            if (*dest == '\0') {
#ifdef SAFECLIB_STR_NULL_SLACK
                /* null slack to clear any data */
                while (dmax) { *dest = '\0'; dmax--; dest++; }
#endif
                return RCNEGATE(EOK);
            }

            dmax--;
            dest++;
            src++;
        }
    }

    /*
     * the entire src must have been copied, if not reset dest
     * to null the string.
     */
    handle_error(orig_dest, orig_dmax, "strcpy_s: not "
                 "enough space for src",
                 ESNOSPC);
    return RCNEGATE(ESNOSPC);
}
Example #14
0
/**
 * NAME
 *    strncat_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strncat_s(char *dest, rsize_t dmax, const char *src, rsize_t slen)
 *
 * DESCRIPTION
 *    The strncat_s function appends a copy of the string pointed
 *    to by src (including the terminating null character) to the
 *    end of the string pointed to by dest. The initial character
 *    from src overwrites the null character at the end of dest.
 *
 *    All elements following the terminating null character (if
 *    any) written by strncat_s in the array of dmax characters
 *    pointed to by dest take unspecified values when strncat_s returns.
 *
 * SPECIFIED IN
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest      pointer to string that will be extended by src
 *              if dmax allows. The string is null terminated.
 *              If the resulting concatenated string is less
 *              than dmax, the remaining slack space is nulled.
 *
 *    dmax      restricted maximum length of the resulting dest,
 *              including the null
 *
 *    src       pointer to the string that will be concatenaed
 *              to string dest
 *
 *    slen      maximum characters to append
 *
 * OUTPUT PARAMETERS
 *    dest      updated string
 *
 * RUNTIME CONSTRAINTS
 *    Neither dest nor src shall be a null pointer
 *    dmax shall not equal zero
 *    dmax shall not be greater than RSIZE_STR_MAX
 *    dmax shall be greater than strnlen_s(src,m).
 *    Copying shall not takeplace between objects that overlap
 *    If there is a runtime-constraint violation, then if dest is
 *       not a null pointer and dmax is greater than zero and not
 *       greater thanRSIZE_MAX, then strncat_s sets dest[0] to the
 *       null character.
 *
 * RETURN VALUE
 *     EOK        successful operation, all the characters from src
 *                   were appended to dest and the result in dest is
 *                   null terminated.
 *     ESNULLP    NULL pointer
 *     ESZEROL    zero length
 *     ESLEMAX    length exceeds max limit
 *     ESUNTERM   dest not terminated
 *
 *
 */
errno_t
strncat_s (char *dest, rsize_t dmax, const char *src, rsize_t slen)
{
    rsize_t orig_dmax;
    char *orig_dest;
    const char *overlap_bumper;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("strncat_s: dest is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (src == NULL) {
        invoke_safe_str_constraint_handler("strncat_s: src is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (slen > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strncat_s: slen exceeds max",
                   NULL, ESLEMAX);
        return RCNEGATE(ESLEMAX);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("strncat_s: dmax is 0",
                   NULL, ESZEROL);
        return RCNEGATE(ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strncat_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return RCNEGATE(ESLEMAX);
    }

    /* hold base of dest in case src was not copied */
    orig_dmax = dmax;
    orig_dest = dest;

    if (dest < src) {
        overlap_bumper = src;

        /* Find the end of dest */
        while (*dest != '\0') {

            if (dest == overlap_bumper) {
                handle_error(orig_dest, orig_dmax, "strncat_s: "
                        "overlapping objects",
                        ESOVRLP);
                return RCNEGATE(ESOVRLP);
            }

            dest++;
            dmax--;
            if (dmax == 0) {
                handle_error(orig_dest, orig_dmax, "strncat_s: "
                       "dest unterminated",
                       ESUNTERM);
                return RCNEGATE(ESUNTERM);
            }
        }

        while (dmax > 0) {
            if (dest == overlap_bumper) {
                handle_error(orig_dest, orig_dmax, "strncat_s: "
                       "overlapping objects",
                       ESOVRLP);
                return RCNEGATE(ESOVRLP);
            }

            /*
             * Copying truncated before the source null is encountered
             */
            if (slen == 0) {
#ifdef SAFECLIB_STR_NULL_SLACK
                /* null remaining string */
                while (dmax) { *dest = '\0'; dmax--; dest++; }
#else
                *dest = '\0';
#endif
                return RCNEGATE(EOK);
            }

            *dest = *src;
            if (*dest == '\0') {
#ifdef SAFECLIB_STR_NULL_SLACK
                /* null slack to clear data */
                while (dmax) { *dest = '\0'; dmax--; dest++; }
#endif
                return RCNEGATE(EOK);
            }

            dmax--;
            slen--;
            dest++;
            src++;
        }

    } else {
        overlap_bumper = dest;

        /* Find the end of dest */
        while (*dest != '\0') {

            /*
             * NOTE: no need to check for overlap here since src comes first
             * in memory and we're not incrementing src here.
             */
            dest++;
            dmax--;
            if (dmax == 0) {
                handle_error(orig_dest, orig_dmax, "strncat_s: "
                       "dest unterminated",
                       ESUNTERM);
                return RCNEGATE(ESUNTERM);
            }
        }

        while (dmax > 0) {
            if (src == overlap_bumper) {
                handle_error(orig_dest, orig_dmax, "strncat_s: "
                        "overlapping objects",
                        ESOVRLP);
                return RCNEGATE(ESOVRLP);
            }

            /*
             * Copying truncated
             */
            if (slen == 0) {
#ifdef SAFECLIB_STR_NULL_SLACK
                /* null remaining string */
                while (dmax) { *dest = '\0'; dmax--; dest++; }
#else
                *dest = '\0';
#endif
                return RCNEGATE(EOK);
            }

            *dest = *src;
            if (*dest == '\0') {
#ifdef SAFECLIB_STR_NULL_SLACK
                /* null slack to clear any data */
                while (dmax) { *dest = '\0'; dmax--; dest++; }
#endif
                return RCNEGATE(EOK);
            }

            dmax--;
            slen--;
            dest++;
            src++;
        }
    }

    /*
     * the entire src was not copied, so the string will be nulled.
     */
    handle_error(orig_dest, orig_dmax, "strncat_s: not enough "
                 "space for src",
                 ESNOSPC);
    return RCNEGATE(ESNOSPC);
}
Example #15
0
/**
 * NAME
 *    strljustify_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    strljustify_s(char *dest, rsize_t dmax)
 *
 * DESCRIPTION
 *    Removes beginning whitespace from the string pointed to by
 *    dest by shifting the text left over writting the beginning
 *    whitespace, left justifying the text.  The left justified
 *    text is null terminated.
 *
 *    The text is shifted so the original pointer can continue
 *    to be used.
 *
 * EXTENSION TO
 *    ISO/IEC JTC1 SC22 WG14 N1172, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest    pointer to string to left justify
 *
 *    dmax    restricted maximum length of string
 *
 * OUTPUT PARAMETERS
 *    dest    left justified
 *
 * RUNTIME CONSTRAINTS
 *    dest shall not be a null pointer.
 *    dmax shall not be 0
 *    dmax shall not be greater than RSIZE_MAX_STR
 *    dest shall be null terminated
 *
 * RETURN VALUE
 *    EOK
 *    ESNULLP     NULL pointer
 *    ESZEROL     zero length
 *    ESLEMAX     length exceeds max limit
 *    ESUNTERM    dest was not null terminated
 *
 * ALSO SEE
 *    strremovews_s(),
 *
 */
errno_t
strljustify_s (char *dest, rsize_t dmax)
{
    char *orig_dest;
    rsize_t orig_dmax;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("strljustify_s_s: "
                   "dest is null",
                   NULL, ESNULLP);
        return (ESNULLP);
    }

    if (dmax == 0 ) {
        invoke_safe_str_constraint_handler("strljustify_s_s: "
                   "dmax is 0",
                   NULL, ESZEROL);
        return (ESZEROL);
    }

    if (dmax > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("strljustify_s_s: "
                   "dmax exceeds max",
                   NULL, ESLEMAX);
        return (ESLEMAX);
    }

    /*
     * corner case, a dmax of one allows only for a null
     */
    if (*dest == '\0' || dmax <= RSIZE_MIN_STR) {
        *dest = '\0';
        return (EOK);
    }

    orig_dmax = dmax;
    orig_dest = dest;

     /*
      * scan the string to be sure it is properly terminated
      */
     while (*dest) {
        if (dmax == 0) {
            while (orig_dmax) { *orig_dest++ = '\0';  orig_dmax--; }

            invoke_safe_str_constraint_handler(
                      "strljustify_s: dest is unterminated",
                       NULL, ESUNTERM);
            return (ESUNTERM);
        }
        dmax--;
        dest++;
    }

    /*
     * find first non-white space char
     */
    dest = orig_dest;
    while ((*dest == ' ') || (*dest == '\t')) {
        dest++;
    }

   /*
    * shift text, removing spaces, to left justify
    */
    if (orig_dest != dest && *dest) {
        while (*dest) {
            *orig_dest++ = *dest;
            *dest++ = ' ';
        }
        *orig_dest = '\0';
    }

    return (EOK);
}
/**
 * NAME
 *    wcscat_s
 *
 * SYNOPSIS
 *    #include "safe_str_lib.h"
 *    errno_t
 *    wcscat_s(wchar_t* dest, rsize_t dmax, const wchar_t* src)
 *
 * DESCRIPTION
 *    The wcscat_s function appends a copy of the wide characer string pointed
 *    to by src (including the terminating null character) to the
 *    end of the string pointed to by dest. The initial wide character
 *    from src overwrites the null character at the end of dest.
 *
 *    All elements following the terminating null character (if
 *    any) written by strcat_s in the array of dmax characters
 *    pointed to by dest take unspecified values when strcat_s
 *    returns.
 *
 * SPECIFIED IN
 *    ISO/IEC TR 24731, Programming languages, environments
 *    and system software interfaces, Extensions to the C Library,
 *    Part I: Bounds-checking interfaces
 *
 * INPUT PARAMETERS
 *    dest      pointer to wide character string that will be extended by src
 *              if dmax allows. The string is null terminated.
 *              If the resulting concatenated string is less
 *              than dmax, the remaining slack space is nulled.
 *
 *    dmax      restricted maximum length of the resulting dest,
 *              including the null
 *
 *    src       pointer to the string that will be concatenaed
 *              to string dest
 *
 * OUTPUT PARAMETERS
 *    dest      is updated
 *
 * RUNTIME CONSTRAINTS
 *    Neither dest nor src shall be a null pointer
 *    dmax shall not equal zero
 *    dmax shall not be greater than RSIZE_MAX_STR
 *    dmax shall be greater than strnlen_s(src,m).
 *    Copying shall not takeplace between objects that overlap
 *    If there is a runtime-constraint violation, then if dest is
 *       not a null pointer and dmax is greater than zero and not
 *       greater than RSIZE_MAX_STR, then strcat_s nulls dest.
 *
 * RETURN VALUE
 *    EOK        successful operation, all the characters from src
 *                were appended to dest and the result in dest is
 *                 null terminated.
 *    ESNULLP    NULL pointer
 *    ESZEROL    zero length
 *    ESLEMAX    length exceeds max
 *    ESUNTERM   dest not terminated
 *
 * ALSO SEE
 *    strcat_s, strncat_s(), strcpy_s(), strncpy_s()
 *
 */
errno_t
wcscat_s(wchar_t* dest, rsize_t dmax, const wchar_t* src)
{
    rsize_t orig_dmax;
    wchar_t *orig_dest;
    const wchar_t *overlap_bumper;

    if (dest == NULL) {
        invoke_safe_str_constraint_handler("wcscat_s: dest is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (src == NULL) {
        invoke_safe_str_constraint_handler("wcscat_s: src is null",
                   NULL, ESNULLP);
        return RCNEGATE(ESNULLP);
    }

    if (dmax == 0) {
        invoke_safe_str_constraint_handler("wcscat_s: dmax is 0",
                   NULL, ESZEROL);
        return RCNEGATE(ESZEROL);
    }

    if (dmax*sizeof(wchar_t) > RSIZE_MAX_STR) {
        invoke_safe_str_constraint_handler("wcscat_s: dmax exceeds max",
                   NULL, ESLEMAX);
        return RCNEGATE(ESLEMAX);
    }

    /* hold base of dest in case src was not copied */
    orig_dmax = dmax;
    orig_dest = dest;

    if (dest < src) {
        overlap_bumper = src;

        /* Find the end of dest */
        while (*dest != L'\0') {

            if (dest == overlap_bumper) {
                handle_wc_error(orig_dest, orig_dmax, "wcscat_s: overlapping objects",
                             ESOVRLP);
                return RCNEGATE(ESOVRLP);
            }

            dest++;
            dmax--;
            if (dmax == 0) {
                handle_wc_error(orig_dest, orig_dmax, "wcscat_s: dest unterminated",
                             ESUNTERM);
                return RCNEGATE(ESUNTERM);
            }
        }

        while (dmax > 0) {
            if (dest == overlap_bumper) {
                handle_wc_error(orig_dest, orig_dmax, "wcscat_s: overlapping objects",
                             ESOVRLP);
                return RCNEGATE(ESOVRLP);
            }

            *dest = *src;
            if (*dest == L'\0') {
#ifdef SAFECLIB_STR_NULL_SLACK
                /* null slack to clear any data */
                while (dmax) { *dest = L'\0'; dmax--; dest++; }
#endif
                return RCNEGATE(EOK);
            }

            dmax--;
            dest++;
            src++;
        }

    } else {
        overlap_bumper = dest;

        /* Find the end of dest */
        while (*dest != L'\0') {

            /*
             * NOTE: no need to check for overlap here since src comes first
             * in memory and we're not incrementing src here.
             */
            dest++;
            dmax--;
            if (dmax == 0) {
                handle_wc_error(orig_dest, orig_dmax, "wcscat_s: dest unterminated",
                             ESUNTERM);
                return RCNEGATE(ESUNTERM);
            }
        }

        while (dmax > 0) {
            if (src == overlap_bumper) {
                handle_wc_error(orig_dest, orig_dmax, "wcscat_s: overlapping objects",
                             ESOVRLP);
                return RCNEGATE(ESOVRLP);
            }

            *dest = *src;
            if (*dest == L'\0') {
#ifdef SAFECLIB_STR_NULL_SLACK
                /* null slack to clear any data */
                while (dmax) { *dest = L'\0'; dmax--; dest++; }
#endif
                return RCNEGATE(EOK);
            }

            dmax--;
            dest++;
            src++;
        }
    }

    /*
     * the entire src was not copied, so null the string
     */
    handle_wc_error(orig_dest, orig_dmax, "wcscat_s: not enough space for src",
                      ESNOSPC);

    return RCNEGATE(ESNOSPC);
}