diff --git a/stdlib/src/builtin/io.mojo b/stdlib/src/builtin/io.mojo index a409c35c62..99f61bcd74 100644 --- a/stdlib/src/builtin/io.mojo +++ b/stdlib/src/builtin/io.mojo @@ -67,7 +67,7 @@ struct _fdopen[mode: StringLiteral = "a"]: """Closes the file handle.""" _ = fclose(self.handle) - fn readline(self) -> String: + fn readline(self) raises -> String: """Reads an entire line from stdin or until EOF. Lines are delimited by a newline character. Returns: @@ -94,7 +94,7 @@ struct _fdopen[mode: StringLiteral = "a"]: """ return self.read_until_delimiter("\n") - fn read_until_delimiter(self, delimiter: String) -> String: + fn read_until_delimiter(self, delimiter: String) raises -> String: """Reads an entire line from a stream, up to the `delimiter`. Does not include the delimiter in the result. @@ -139,6 +139,12 @@ struct _fdopen[mode: StringLiteral = "a"]: ord(delimiter), self.handle, ) + # Per man getdelim(3), getdelim will return -1 if an error occurs + # (or the user sends EOF without providing any input). We must + # raise an error in this case because otherwise, String() will crash mojo + # if the user sends EOF with no input. + if bytes_read == -1: + raise Error("received EOF") # Copy the buffer (excluding the delimiter itself) into a Mojo String. var s = String(StringRef(buffer, bytes_read - 1)) # Explicitly free the buffer using free() instead of the Mojo allocator. @@ -286,7 +292,7 @@ fn print[ # ===----------------------------------------------------------------------=== # -fn input(prompt: String = "") -> String: +fn input(prompt: String = "") raises -> String: """Reads a line of input from the user. Reads a line from standard input, converts it to a string, and returns that string.