Talk:Longest string challenge: Difference between revisions

Content added Content deleted
(→‎Comments / Feedback: doc tweak above)
(→‎bounds checking in C: the unsightly but more correct code (why do we worry about bounds in *this* example?))
Line 260: Line 260:
:Segfault isn't all that different from <code>kill -9</code>, or even calling <code>exit()</code> for that matter: the process is gone, along with all its memory pages and file handles, leaving not much to be compromised. A crashed program of course can leave behind some inconsistent state around such as half written files, but that's not a problem here. The C code can overrun buffers even if we use <code>fgets</code> (and the fgets length should be 1 less anyway), so the last fix didn't really fix anything, only adding a possibility of wrong result besides crashing. If there is a chance for the program to fail and we are not going to completely prevent it, I'd rather have it fail more obviously. --[[User:Ledrug|Ledrug]] 03:13, 15 August 2011 (UTC)
:Segfault isn't all that different from <code>kill -9</code>, or even calling <code>exit()</code> for that matter: the process is gone, along with all its memory pages and file handles, leaving not much to be compromised. A crashed program of course can leave behind some inconsistent state around such as half written files, but that's not a problem here. The C code can overrun buffers even if we use <code>fgets</code> (and the fgets length should be 1 less anyway), so the last fix didn't really fix anything, only adding a possibility of wrong result besides crashing. If there is a chance for the program to fail and we are not going to completely prevent it, I'd rather have it fail more obviously. --[[User:Ledrug|Ledrug]] 03:13, 15 August 2011 (UTC)
::Segfault is not the only possible outcome from buffer overflow. Also, it's my understanding that the length argument to fgets is the buffer size -- if it's 65536 then a maximum of 65535 characters will be read as the final character to be placed in the buffer must be null. That said, if there were some other way to crash the program, I would like to understand it, and I would also like for that issue to be fixed. --[[User:Rdm|Rdm]] 17:07, 15 August 2011 (UTC)
::Segfault is not the only possible outcome from buffer overflow. Also, it's my understanding that the length argument to fgets is the buffer size -- if it's 65536 then a maximum of 65535 characters will be read as the final character to be placed in the buffer must be null. That said, if there were some other way to crash the program, I would like to understand it, and I would also like for that issue to be fixed. --[[User:Rdm|Rdm]] 17:07, 15 August 2011 (UTC)
:::The fgets needs to be 1 less because of the strcat of a newline right after it. Even with fgets, the accumulator buffer <code>buf</code> can still be overrun when we add lines to it (suppose the input has 2000 lines each 1000 chars long, for example). If you want to be safe, well, <lang c>#include <stdio.h>
#include <string.h>
#include <assert.h>

int cmp(const char *p, const char *q)
{
while (*p && *q) {
p = &p[1];
q = &q[1];
}
return *p;
}

int inc(int x) { return (int)&((char *)x)[1]; }
int dec(int x) { return (int)&((char *)x)[-1]; }
int gt(int x, int y)
{
while (y && x) y = dec(y), x = dec(x);
return x;
}

int add(int x, int y)
{
while(y) x = inc(x), y = dec(y);
return x;
}

/* strlen(a) + 1 */
int length(char *a)
{
char *x = 0;
while (*a) a = &a[1], x = &x[1];
return (int)x;
}

#define LINE_MAX 10
#define ACCU_MAX 30
int main()
{
char line[LINE_MAX];
char buf[ACCU_MAX] = {0};
char *last = buf;
char *next = buf;
while (fgets(line, LINE_MAX, stdin)) {
assert(gt(dec(LINE_MAX), length(line)));

if (cmp(last, line)) continue;
if (cmp(line, last)) next = buf;
last = next;

assert(!gt(add(length(buf), length(line)), ACCU_MAX));

strcpy(next, line);
while (*next) next = &next[1];
}
printf("%s", buf);
return 0;
}</lang> I haven't carefully checked all the comparisons in the above, but it's on the right track at least. --[[User:Ledrug|Ledrug]] 00:17, 17 August 2011 (UTC)
::In other words, this program will not block for input: <lang c>#include <stdio.h>
::In other words, this program will not block for input: <lang c>#include <stdio.h>
main() {
main() {