# cat strnlen_broken.c #include <string.h> #include <stdlib.h> main() { char *s1 = "01234567891"; printf("strlen %d\n",strlen(s1)); printf("strnlen %d\n",strnlen(s1,10)); } # cc strnlen_broken.c # ./a.out strlen 11 strnlen 11 strnlen should return 10! I couldn't find a short example of the wrong behavior of strndup. When i insterted DEBUG befor and after strndup in the Samba code, I saw that no '\0' is put on the end. So sometimes I saw remainings of previously used strings after the duplicated string.
Hmm that doesn't look good does it? A bit of research on the open group web site shows that strnlen() isn't part of IEEE 1003.1 and so there is no official description of how strnlen should behave. Are you seeing some strange errors because of this?
Created attachment 409 [details] Details for strndup bug
OK that is pretty bad. I can code up a configure test and a replacement strnlen() function if a broken one is detected.
Both functions already are in lib/util_str.c It's only a configure issue.
Ah OK - thanks for the tip. That will save a bit of work.
Created attachment 416 [details] Configure test for broken strnlen Here's the first version of a configure test. Would you be able to test it out? Also, if you can describe how strndup() is broken I can write a test for it as well. If it's broken in the same way as strnlen() then it probably ignores the length argument.
Looks good to me. As already mentioned, I couldn't find a short example for strndup's failure. I think it works like this: char *strndup(char * in, int n) { char *out = malloc(n+1); memcpy(out,in,n); /* *out = 0; is missing */ return out; } If the malloced buffer contains zeros, this will work, otherwise garbage is at the end. I tried several sequences of strndup, malloc, free but couldn't trigger the error. Since a search for strnlen and strndup in AIX's documntation won't find anything, I would consider both undocumented and not existent. I suggest to not use them at all: if OS == AIX undef HAVE_STRNDUP undef HAVE_STRNLEN endif This could be changed to if AIX < 5.x.x as soon as an AIX version is known to support both offically.
(In reply to comment #7) Can you check if this test triggers the problem ? #include <string.h> #include <stdlib.h> main() { char *test = "0123456789"; char *control = "01234567"; char *verify; verify = strndup(test, 8); if (strcmp(control, verify)) printf("strndup is broken\n"); } Simo
No, this does not trigger the problem, but now I think I found it: #include <string.h> #include <stdlib.h> #include <stdio.h> main() { char *test1 = "abcdefghijk"; char *test2 = "0123456789"; char *control = "012345678"; char *verify; free(strndup(test1, 10)); verify = strndup(test2, 9); /* shorter then first strndup !!! */ fprintf(stderr,">%s<\n",verify); if (strcmp(control, verify)) printf("strndup is broken\n"); } If compiled with -q32 This prints >012345678j< strndup is broken It does not happen when anyone of the following is true: * the free is left out * the length of the second strndup is larger then of the first one. * compiled with -q64 (64 bit). Note that the strnlen bug happens regardless of 32 or 64 bit.
(In reply to comment #9) > * compiled with -q64 (64 bit). Sorry! i was to fast. The following failes regardless of 32 or 64 bit: #include <string.h> #include <stdlib.h> #include <stdio.h> main() { char *test1 = "abcdefghijabcdefghijabcdefghijk"; char *test2 = "012345678901234567890123456789"; char *control = "01234567890123456789012345678"; char *verify; free(strndup(test1, 30)); verify = strndup(test2, 29); /* shorter then first strndup !!! */ fprintf(stderr,">%s<\n",verify); if (strcmp(control, verify)) printf("strndup is broken\n"); }
(In reply to comment #10) Confirmed, with the following test I get wrong results. int main(void) { char *test = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuwxyz"; char *control = "0123456789012345678901234567890123456789"; char *verify; verify = strndup(test,45); printf("strndup n.1: [%s]\n", verify); free(verify); verify = strndup(control,30); printf("strndup n.2: [%s]\n", verify); } Simo.
Is this still an issue on 3.0.11 ? Please reopen if necessary.
sorry for the same, cleaning up the database to prevent unecessary reopens of bugs.