On Mon, 10 Apr 2023 04:28:34 GMT, Chen Liang <li...@openjdk.org> wrote:
>> Nah. I mean like: >> >> public static String join(CharSequence delimiter, >> Iterable<? extends CharSequence> elements) { >> Objects.requireNonNull(delimiter); >> Objects.requireNonNull(elements); >> var delim = delimiter.toString(); >> Object[] elems; >> final int size; >> if (elements instanceof Collection<?> c) { >> elems = c.toArray(); >> size = elems.length; >> for (int i = 0; i < size; i++) { >> elems[i] = String.valueOf(elems[i]); >> } >> } else { >> elems = new String[elements instanceof Collection<?> c ? >> c.size() : 8]; // or whatever spliterator you decide to use >> size = 0; >> for (CharSequence cs: elements) { >> if (size >= elems.length) { >> elems = Arrays.copyOf(elems, elems.length << 1); >> } >> elems[size++] = String.valueOf(cs); >> } >> } >> return join("", "", delim, elems, size); >> } >> // ... >> static String join(String prefix, String suffix, String delimiter, Object[] >> elements, int size) { // change array type to Object[], cast on access >> elements > >> @liach I don't think it's safe because `c.toArray()` can return an array >> that may be modified by others. In fact, although the specification of >> `Collection.toArray()` indicates that the returned array is free to be >> modified, nobody actually trusts this contract. They only trust `ArrayList` >> which is most widely-used. > > It's safe. We don't keep the array in another object, and it's discarded > after we finish the join. The most risky scenario is that the array is shared > to another thread that can execute in parallel with the malicious Collection, > which can swap out the String elements in the array we've obtained with > irrelevant items. > > Then you might go for > https://github.com/openjdk/jdk/pull/13383#issuecomment-1501340839 but it > involves one extra array copy. But @liach 's sample modifies the returned array directly. It cause problems with this situation: class BadList implements List<Object> { private Object[] array; public Object get(int i) { return array[i]; } public Object[] toArray() { return array; // no clone } // ... } Modifying the array will accidentally modify the collection implemented as above. That's why we should not trust that the array is *safe to be modified*. ------------- PR Comment: https://git.openjdk.org/jdk/pull/13383#issuecomment-1501387583