From 7f5168769dbac43937209543c8e535773d8aa863 Mon Sep 17 00:00:00 2001 From: Erik Rauer Date: Thu, 28 Jan 2021 16:25:00 -0600 Subject: [PATCH] Add methods to prevent numbers, vectors and strings from getting too big This should prevent numbers from getting too big or small, as well as prevent strings and vectors from getting too long. All the code was written by @mcgirjau and can be found here: https://github.com/mcgirjau/propeller/commit/b75e000a380b7d14b63bd05aa0ca76c388e73001 --- src/propeller/push/utils/globals.cljc | 21 +++++++++++- src/propeller/push/utils/helpers.cljc | 49 +++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/propeller/push/utils/globals.cljc b/src/propeller/push/utils/globals.cljc index 26c37f1..aad494b 100644 --- a/src/propeller/push/utils/globals.cljc +++ b/src/propeller/push/utils/globals.cljc @@ -8,4 +8,23 @@ ;; Limits the number of items that can be duplicated onto a stack at once. ;; We might want to extend this to limit all the different that things may be ;; placed on a stack. -(def max-stack-items 100) \ No newline at end of file +(def max-stack-items 100) + + + +;; ============================================================================= +;; Values used by the Push instructions to keep computed values within +;; reasonable size limits. +;; ============================================================================= + +;; Used by keep-number-reasonable as the maximum magnitude of any integer/float +(def max-number-magnitude 1.0E12) + +;; Used by keep-number-reasonable as the minimum magnitude of any float +(def min-number-magnitude 1.0E-10) + +;; Used by reasonable-string-length? to ensure that strings don't get too large +(def max-string-length 1000) + +;; Used by keep-vector-reasonable to ensure that vectors don't get too large +(def max-vector-length 1000) \ No newline at end of file diff --git a/src/propeller/push/utils/helpers.cljc b/src/propeller/push/utils/helpers.cljc index 4eccfb6..1596827 100755 --- a/src/propeller/push/utils/helpers.cljc +++ b/src/propeller/push/utils/helpers.cljc @@ -2,9 +2,40 @@ (:require [clojure.set] [propeller.push.core :as push] [propeller.push.state :as state] + [propeller.push.utils.globals :as globals] #?(:cljs [goog.string :as gstring]) #?(:cljs [goog.string.format]))) +;; Returns a version of the number n that is within reasonable size bounds +(defn keep-number-reasonable + [n] + (cond + (integer? n) + (cond + (> n globals/max-number-magnitude) (long globals/max-number-magnitude) + (< n (- globals/max-number-magnitude)) (long (- globals/max-number-magnitude)) + :else n) + :else + (cond + (Double/isNaN n) 0.0 + (or (= n Double/POSITIVE_INFINITY) + (> n globals/max-number-magnitude)) globals/max-number-magnitude + (or (= n Double/NEGATIVE_INFINITY) + (< n (- globals/max-number-magnitude))) (- globals/max-number-magnitude) + (< (- globals/min-number-magnitude) n globals/min-number-magnitude) 0.0 + :else n))) + +;; Returns true if the string is of a reasonable size +(defn reasonable-string-length? + [string] + (let [length (count string)] + (<= length globals/max-string-length))) + +;; Returns true if the vector is of a reasonable size +(defn reasonable-vector-length? + [vector] + (let [length (count vector)] + (<= length globals/max-vector-length))) ;; Takes a state and a collection of stacks to take args from. If there are ;; enough args on each of the desired stacks, returns a map with keys @@ -40,9 +71,23 @@ state (let [result (apply function (:args popped-args)) new-state (:state popped-args)] - (if (= result :ignore-instruction) + (cond + (number? result) + (state/push-to-stack new-state return-stack (keep-number-reasonable result)) + ;; + (and (string? result) + (not (reasonable-string-length? result))) state - (state/push-to-stack new-state return-stack result)))))) + ;; + (and (vector? result) + (not (reasonable-vector-length? result))) + state + ;; + (= result :ignore-instruction) + state + ;; + :else + (state/push-to-stack new-state return-stack result)))))) ;; Given a set of stacks, returns all instructions that operate on those stacks ;; only. Won't include random instructions unless :random is in the set as well