Skip to content

Commit 8971cec

Browse files
committed
Audit of caml_read_fd: update offset and max pointer
Only stdin is global in Stdlib, and it is not seekable, so its state remained valid on exception. However it does not cost much to keep the offset and the max pointer up to date in all situtations when an interrupt arises. In addition, one can be suspicious that channel locks may leak, which can cause deadlocks. However, this is already dealt with Unlock_exn.
1 parent 67250e5 commit 8971cec

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

runtime/io.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,25 @@ CAMLexport int caml_read_fd(int fd, int flags, void * buf, int n)
301301
return retcode;
302302
}
303303

304-
/* caml_do_read is exported for Cash */
304+
// raises
305+
static int read_fd_into_channel(struct channel * channel, char * buf)
306+
{
307+
int n;
308+
value exn = Val_unit;
309+
n = caml_read_fd_exn(channel->fd, channel->flags, buf,
310+
channel->end - buf, &exn);
311+
if (n <= 0) {
312+
caml_raise_if_exception(exn);
313+
CAMLassert(n == 0);
314+
return n;
315+
}
316+
channel->offset += n;
317+
channel->max = buf + n;
318+
caml_raise_if_exception(exn);
319+
return n;
320+
}
321+
322+
/* caml_do_read is exported for Cash. Raises. */
305323
CAMLexport int caml_do_read(int fd, char *p, unsigned int n)
306324
{
307325
return caml_read_fd(fd, 0, p, n);
@@ -310,12 +328,8 @@ CAMLexport int caml_do_read(int fd, char *p, unsigned int n)
310328
CAMLexport unsigned char caml_refill(struct channel *channel)
311329
{
312330
int n;
313-
314-
n = caml_read_fd(channel->fd, channel->flags,
315-
channel->buff, channel->end - channel->buff);
331+
n = read_fd_into_channel(channel, channel->buff);
316332
if (n == 0) caml_raise_end_of_file();
317-
channel->offset += n;
318-
channel->max = channel->buff + n;
319333
channel->curr = channel->buff + 1;
320334
return (unsigned char)(channel->buff[0]);
321335
}
@@ -349,10 +363,7 @@ CAMLexport int caml_getblock(struct channel *channel, char *p, intnat len)
349363
channel->curr += avail;
350364
return avail;
351365
} else {
352-
nread = caml_read_fd(channel->fd, channel->flags, channel->buff,
353-
channel->end - channel->buff);
354-
channel->offset += nread;
355-
channel->max = channel->buff + nread;
366+
nread = read_fd_into_channel(channel, channel->buff);
356367
if (n > nread) n = nread;
357368
memmove(p, channel->buff, n);
358369
channel->curr = channel->buff + n;
@@ -421,16 +432,13 @@ CAMLexport intnat caml_input_scan_line(struct channel *channel)
421432
return -(channel->max - channel->curr);
422433
}
423434
/* Fill the buffer as much as possible */
424-
n = caml_read_fd(channel->fd, channel->flags,
425-
channel->max, channel->end - channel->max);
435+
n = read_fd_into_channel(channel, channel->max);
426436
if (n == 0) {
427437
/* End-of-file encountered. Return the number of characters in the
428438
buffer, with negative sign since we haven't encountered
429439
a newline. */
430440
return -(channel->max - channel->curr);
431441
}
432-
channel->offset += n;
433-
channel->max += n;
434442
}
435443
} while (*p++ != '\n');
436444
/* Found a newline. Return the length of the line, newline included. */

0 commit comments

Comments
 (0)