From d757c20e3fcdd30ab6f0752306ea8b15c89a6385 Mon Sep 17 00:00:00 2001 From: Mike Fikes Date: Sun, 11 Aug 2019 20:05:54 -0400 Subject: [PATCH] Crash if writing large byte vector to output stream (#1002) Fixes #1001 --- CHANGELOG.md | 5 ++++ planck-c/functions.c | 39 ++++++++++++++-------------- planck-cljs/test/planck/io_test.cljs | 12 ++++++++- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a2cc594..fe0407b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). +## [Unreleased] +### Fixed +- Crash if writing large byte vector to output stream ([#1001](https://github.com/planck-repl/planck/issues/1001)) + ## [2.24.0] - 2019-07-25 ### Added - Native temp file and dir facilities ([#934](https://github.com/planck-repl/planck/issues/934)) @@ -857,6 +861,7 @@ All notable changes to this project will be documented in this file. This change ### Added - Initial release. +[Unreleased]: https://github.com/mfikes/planck/compare/2.24.0...HEAD [2.24.0]: https://github.com/mfikes/planck/compare/2.23.0...2.24.0 [2.23.0]: https://github.com/mfikes/planck/compare/2.22.0...2.23.0 [2.22.0]: https://github.com/mfikes/planck/compare/2.21.0...2.22.0 diff --git a/planck-c/functions.c b/planck-c/functions.c index 1a3f2379..2ed371ea 100644 --- a/planck-c/functions.c +++ b/planck-c/functions.c @@ -30,6 +30,12 @@ #include "sockets.h" #include "tasks.h" +JSValueRef make_error_with_errno(JSContextRef ctx) { + JSValueRef arguments[1]; + arguments[0] = c_string_to_value(ctx, strerror(errno)); + return JSObjectMakeError(ctx, 1, arguments, NULL); +} + #define CONSOLE_LOG_BUF_SIZE 1000 char console_log_buf[CONSOLE_LOG_BUF_SIZE]; @@ -902,7 +908,13 @@ JSValueRef function_file_output_stream_write(JSContextRef ctx, JSObjectRef funct char *descriptor = value_to_c_string(ctx, args[0]); unsigned int count = (unsigned int) array_get_count(ctx, (JSObjectRef) args[1]); - uint8_t buf[count]; + + uint8_t* buf = malloc(sizeof(uint8_t) * count); + if (!buf) { + *exception = make_error_with_errno(ctx); + return JSValueMakeNull(ctx); + } + unsigned int i; for (i = 0; i < count; i++) { JSValueRef v = array_get_value_at_index(ctx, (JSObjectRef) args[1], i); @@ -920,6 +932,7 @@ JSValueRef function_file_output_stream_write(JSContextRef ctx, JSObjectRef funct file_write(descriptor_str_to_int(descriptor), count, buf); + free(buf); free(descriptor); } @@ -988,9 +1001,7 @@ JSValueRef function_copy_file(JSContextRef ctx, JSObjectRef function, JSObjectRe int rv = copy_file(src, dst); if (rv) { - JSValueRef arguments[1]; - arguments[0] = c_string_to_value(ctx, strerror(errno)); - *exception = JSObjectMakeError(ctx, 1, arguments, NULL); + *exception = make_error_with_errno(ctx); } free(src); @@ -1090,9 +1101,7 @@ JSValueRef function_mktemp(JSContextRef ctx, JSObjectRef function, JSObjectRef t if (temp_name) { return c_string_to_value(ctx, temp_name); } else { - JSValueRef arguments[1]; - arguments[0] = c_string_to_value(ctx, strerror(errno)); - *exception = JSObjectMakeError(ctx, 1, arguments, NULL); + *exception = make_error_with_errno(ctx); } } @@ -1447,9 +1456,7 @@ JSValueRef function_socket_connect(JSContextRef ctx, JSObjectRef function, JSObj int sock = connect_socket(host, port, socket_conn_data_arrived, data_arrived_info); if (sock == -1) { - JSValueRef arguments[1]; - arguments[0] = c_string_to_value(ctx, strerror(errno)); - *exception = JSObjectMakeError(ctx, 1, arguments, NULL); + *exception = make_error_with_errno(ctx); } else { return JSValueMakeNumber(ctx, sock); } @@ -1479,9 +1486,7 @@ JSValueRef function_socket_listen(JSContextRef ctx, JSObjectRef function, JSObje int err = bind_and_listen(socket_accept_info); if (err == -1) { - JSValueRef arguments[1]; - arguments[0] = c_string_to_value(ctx, strerror(errno)); - *exception = JSObjectMakeError(ctx, 1, arguments, NULL); + *exception = make_error_with_errno(ctx); } else { pthread_t thread; pthread_create(&thread, NULL, accept_connections, socket_accept_info); @@ -1501,9 +1506,7 @@ JSValueRef function_socket_write(JSContextRef ctx, JSObjectRef function, JSObjec int err = write_to_socket(sock, value_to_c_string(ctx, args[1])); if (err == -1) { - JSValueRef arguments[1]; - arguments[0] = c_string_to_value(ctx, strerror(errno)); - *exception = JSObjectMakeError(ctx, 1, arguments, NULL); + *exception = make_error_with_errno(ctx); } } return JSValueMakeNull(ctx); @@ -1519,9 +1522,7 @@ JSValueRef function_socket_close(JSContextRef ctx, JSObjectRef function, JSObjec int err = close_socket(sock); if (err == -1) { - JSValueRef arguments[1]; - arguments[0] = c_string_to_value(ctx, strerror(errno)); - *exception = JSObjectMakeError(ctx, 1, arguments, NULL); + *exception = make_error_with_errno(ctx); } } return JSValueMakeNull(ctx); diff --git a/planck-cljs/test/planck/io_test.cljs b/planck-cljs/test/planck/io_test.cljs index 117ef5c6..1e096f5c 100644 --- a/planck-cljs/test/planck/io_test.cljs +++ b/planck-cljs/test/planck/io_test.cljs @@ -2,7 +2,7 @@ (:require [clojure.test :refer [deftest is testing]] [clojure.string :as string] - [planck.core :refer [spit slurp with-open]] + [planck.core :refer [spit slurp with-open -write-bytes -read-bytes]] [planck.io :as io] [planck.shell :as shell]) (:import @@ -238,3 +238,13 @@ (let [target-file (io/temp-file)] (io/copy (io/input-stream "http://planck-repl.org/releases/andare/andare-0.2.0.jar") target-file) (is (= 64328 (:file-size (io/file-attributes target-file)))))) + +(deftest write-large-binary-file-test + (let [file (io/temp-file) + content (into [] (take 15485863) (cycle (range 256)))] + (with-open [out-stream (io/output-stream file)] + (-write-bytes out-stream content)) + (with-open [in-stream (io/input-stream file)] + (is (= content (->> (repeatedly #(-read-bytes in-stream)) + (take-while some?) + (reduce into)))))))