/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.Queue; class PurityModeled { double math_random_impure() { return Math.random(); } double math_random_infeasible_pure(int x) { if (x > 1 && x < 2) { return Math.random(); // this path will never be taken } return 0; } void arraycopy_pure_FP(int[] src) { int[] dst = {5, 10, 20, 30, 40, 50}; // copies an array from the specified source array System.arraycopy(src, 0, dst, 0, 1); } public void array_length_loop_pure(Integer[] array) { for (int i = 0; i < array.length; i++) {} } void write_impure() { byte[] temp = new byte[4]; System.out.write(temp, 0, 4); } void call_write_impure() { write_impure(); } int math_random_in_loop_impure(int x) { int p = 0; for (int i = 0; i < x; i++) { p += Math.random(); call_write_impure(); } return p; } void list_size_pure(ArrayList list) { for (int i = 0; i < list.size(); i++) {} } void list_add_impure(ArrayList list) { list.add("a"); } void list_addall_impure(ArrayList list1, ArrayList list2) { list1.addAll(list2); } void enum_loop_pure(Enumeration e) { for (; e.hasMoreElements(); ) { Object o = e.nextElement(); } } void remove_impure(Iterator i) { while (i.hasNext()) { if (i.next().equals("Orange")) { i.remove(); break; } } } void list_set_impure(ArrayList list) { list.set(0, "e"); } // Pulse can only widen a fixed number of times, hence it thinks // that the exit of the loop never reaches and results in empty // post. void timing_call_in_loop_impure_FN() { for (int i = 0; i < 10; i++) { System.nanoTime(); } } // Since n is symbolic, pruning doesn't result in infeasible path, // but we assume that the parameter [n] must be 3 due to constant(4) // "widening" in pulse. void timing_call_in_loop_symb_impure(int n) { for (int i = 0; i < n; i++) { System.nanoTime(); } } // Due to getting the wrong summary for the callee (a=3), Pulse ends // up thinking that the parameter [a] must be 3 in the loop. Hence, as // a result of pruning, exit node becomes infeasible and we get // empty summary. void call_timing_symb_impure_FN(int a) { for (int i = 0; i < a; i++) { timing_call_in_loop_symb_impure(a); } } // The relation between the parameter and the argument to the callee // is broken. Although, the final pulse summary for this function is // still wrong. void call_timing_symb_unrelated_impure(int a, int b) { for (int i = 0; i < a; i++) { timing_call_in_loop_symb_impure(b); } } enum Color { RED, GREEN, BLUE; // values() calls clone } public void enum_iter_pure() { for (Color c : Color.values()) {} } void clone_pure(ArrayList list) { ArrayList cloned = (ArrayList) list.clone(); cloned.add(""); // no change the list } String replace_impure(String s) { return s.replace('a', 'f'); } void process_queue_impure(ArrayList list, Queue queue) { for (Integer el : list) { queue.add(el); } } void append_impure(StringBuilder strBuilder) { strBuilder.append("JavaGuru"); } void append_pure() { StringBuilder strBuilder = new StringBuilder("Core"); strBuilder.append("JavaGuru"); } // Our model of Iterator.next is wrong. It should be modeled as // impure. Integer next_impure_FN(Iterator it) { return it.next(); } }