简体   繁体   中英

Problem of overlap verification between two strings

I am currently recoding srtcat() from the standard C library and I have set up some checks to avoid overlap problems. The problem is that my program still enters the error handling.

Here is the code:

char *my_strcat(char *restrict dest, const char *restrict src)
{
    size_t dest_len = 0, src_len = 0;
    char *p = dest;
    src_len = my_strlen(src);
    if (!dest || !src)
        return NULL;
    dest_len = my_strlen(dest);
    if (src >= dest && src < dest + dest_len) {
        return NULL;
    }
    if (dest >= src && dest < src + src_len) {
        return NULL;
    }
    while (*p != '\0') p++, dest_len++;
    if (dest_len + src_len + 1 > sizeof(dest))
        return NULL;
    p = dest + dest_len;
    while (*src != '\0')
        *p++ = *src++;
    *p = '\0';
    return dest;
}
size_t my_strlen(const char *s)
{
    size_t count = 0;
    if (s != NULL) {
        while (*s != 0) {
            count++;
            s++;
        }
    }
    return count;
}

I tested this way:

int main(int argc, char **argv)
{
    const char *src = "Hello";
    char dest[100] = " world!";
    char *test = my_strcat(dest, src);
    printf("Src : %s Dest : %s\n", src, dest);
    printf("Return adress : %p, Value : %s\n", test, test);
    return 0;
}

According to gdb :

if (src >= dest && src < dest + dest_len) 
1: dest = 0x7fffffffda70 " world!"
2: src = 0x555555557004 "Hello"
3: dest_len = 0
4: src_len = 5

Output

Src : Hello Dest :  world!
Return adress : (nil), Value : (null)

Do you see the problem?

Update

Following your suggestions I have modified the code like this:

char *my_strcat(char *restrict dest, const char *restrict src, size_t d_size)
{
    size_t dest_len = 0, src_len = 0;
    char *p = dest;
    if (!dest || !src)
        return NULL;
    src_len = my_strlen(src);
    dest_len = my_strlen(dest);
    if (src >= dest && src < dest + dest_len) {
        return NULL;
    }
    if (dest >= src && dest < src + src_len) {
        return NULL;
    }
    while (*p != '\0') p++, dest_len++;
    if (dest_len + src_len + 1 > d_size)
        return NULL;
    p = dest + dest_len;
    while (*src != '\0')
        *p++ = *src++;
    *p = '\0';
    return dest;
}

And in the main: char *test = my_strcat(dest, src, sizeof(dest));

But it still doesn't work:

Src : Hello Dest :  world!
Return adress : 0x7fff74bc5650, Value :  world!

Having tried to guide toward understanding this problem, it seems best to present what should be working code (for study.) Sometimes too many words merely muddle the situation:

char *my_strcat(char *restrict dest, const char *restrict src, size_t d_size) {
    if( !dest || !src )
        return NULL;

    size_t src_len = strlen( src );
    size_t dest_len = strlen( dest );

    if( dest_len + src_len + 1 > d_size )
        return NULL;

    char *p = dest + dest_len;
    while( (*p++ = *src++ ) != '\0' )
        ;

    return dest;
}

int main() {
    const char *src = "Hello";
    char dest[100] = " world!";
    printf("Src : %s Dest : %s\n", src, dest);

    char *test = my_strcat( dest, src, sizeof dest );

    if( test )
        printf("Value : %s\n", test );

    return 0;
}

Now, one can experiment by shrinking the size of dest to something larger than " world." but smaller than " world.Hello".?? Perhaps 9 bytes???

And, now that the concatenation should be working (into a big enough buffer), adding the code to ensure there is no overlap of the actual character arrays. Known is the size of dest, and the length of src is measured.

dest_len + src_len + 1 > sizeof(dest)

sizeof(dest) is the size of the pointer sizeof(char*) . If you want to check if the dest will be overflowed, you have to pass the size as an argument. See strlcpy or strncpy .

 src >= dest

Note that comparing pointers that do not point to the same array is technically invalid. To bring some breeze of validity, you can do (uintptr_t)stc >= (uintptr_t)dest . How does pointer comparison work in C? Is it ok to compare pointers that don't point to the same array? Is comparing two pointers with < undefined behavior if they are both cast to an integer type? Why does comparing pointers with undefined behavior still give correct results? etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM