-1

I have the following function:

char    *ft_substr(char const *s, unsigned int start, size_t len)
{
    char    *substr;

    if (!s)
        return (NULL);
    if (start > ft_strlen(s))
        len = 0;
    if (start <= ft_strlen(s) && s[start] != '\0')
    {   
        if (ft_strlen(s + start) < len)
            len = ft_strlen(s + start);
    }
    substr = (char *)malloc(sizeof(*s) * (len + 1));
    if (!substr)
        return (NULL);
    if (len == 0)
        return (substr);
    ft_strlcpy(substr, s + start, len + 1); 
    return (substr);
}

Some of the functions are self-made (strlen = ft_strlen etc).

The problem: if I pass in -1 for "start", my program segfaults because it is converted to 4.294.967.295. So it crashes when passed in that is my function body does not even execute making all protective measures useless. Even stranger, if I execute this on my Mac everything works fine, on Ubuntu 22.04 it does not.

Any suggestions? I am not allowed to change the function prototype.

Edit: I have to pass a series of tests and the following one I am failing constantly:

Error in test 4: ft_substr("hola", 4294967295, 0): Segmentation fault!

(The test actually inputs -1).

Also, I am not allowed to include a main that tests user input.

Edit 2: My main is simple and just calls the function with input "hola", -1, 3

miken32
  • 42,008
  • 16
  • 111
  • 154
  • Don't mix up input sanitation with algorithms. This code here has nothing to do with user input so it shouldn't concern itself with it. Sanitize input at the point where your program takes that input. – Lundin Jan 24 '23 at 13:46
  • 1
    What do you expect `ft_substr` to do with a negative index? – Jabberwocky Jan 24 '23 at 13:49
  • 1
    "Also, I am not allowed to include a main that tests user input." Then you are getting taught bad practices. Proper program design is all about not having code concern itself with unrelated tasks other than its designated purpose. This philosophy is the very core of proper program design. – Lundin Jan 24 '23 at 13:49
  • In the case of `if (len == 0)` you havn't nul-terminated the "empty string" size 1 which is returned. – Weather Vane Jan 24 '23 at 13:50
  • 1
    _"Some of the functions are self-made"_, then you should show them. – ryyker Jan 24 '23 at 13:52
  • Welcome to the 42. If you are having issues with your projects, you should be asking your peers for help as the school is design with peer-learning in mind – Randommm Jan 24 '23 at 13:52
  • @Jabberwocky should be impossible, as any unsigned int MUST be >= 0. I understand that it is not good practice but my school writes tests - I am not allowed to change them. – kaisyteknon Jan 24 '23 at 13:55
  • 1
    @kaisyteknon you pass the signed value -1 to an `unsigned int` parameter which is wrong. What do you expect? – Jabberwocky Jan 24 '23 at 13:58
  • @Randommm - no one is able to fix it. thanks @ ryyker - not necessary, because the program crashes (1) as soon as -1 is passed in as a parameter and (2) even when I use the original functions. – kaisyteknon Jan 24 '23 at 13:58
  • I just ran your code using _standard_ functions, calling `char *a = ft_substr("asdlkjald", -1, 10);` (Except commented strlcpy) and it ran without segfault. The problem is probably in an implementation of your custom functions. – ryyker Jan 24 '23 at 13:59
  • `if (len == 0) return (substr);` will lead to UB because `substr` contains uninitialized memory - it's not a string. Given that `start` is of type `unsigned int`, that would explain the SEGV as a negative value would map to a large positive unsigned value and cause `len` to be set to `0` in the posted code. – Andrew Henle Jan 24 '23 at 14:02
  • 1
    After ft_strlcpy you must terminate the string with '\0'. Also you should copy len, not len+1 – stark Jan 24 '23 at 14:05
  • Could be `substr` not being initialised to `\0` so it's missing a null byte to end of the string. Could also be your ft_strlcpy since you pass len **+1** – Randommm Jan 24 '23 at 14:05

1 Answers1

1

You need to terminate the string you've copied with ft_strlcpy with '\0'. Your bounds checking could also be made a little simpler.

Example:

char *ft_substr(char const *s, unsigned int start, size_t len)
{
    if (!s) return NULL;

    size_t slen = ft_strlen(s);
    
    if (start > slen) {                 // start out of bounds, make empty string
        start = 0;
        len = 0;
    } else if(start + len > slen) {     // len is too large, shrink it
        len = slen - start;
    }

    char *substr = malloc(len + 1);
    if (!substr) return NULL;
    
    ft_strlcpy(substr, s + start, len); // note: copy len, not len+1
    substr[len] = '\0';                 // terminate the string
    
    return substr;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108