1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.eclipse.aether.internal.impl;
20
21 /**
22 * Sanitizes strings that may carry remote-derived bytes (artifact coordinates, checksum values, transfer error
23 * messages) before they are logged or persisted. Bytes received from a remote repository must not be able to
24 * influence terminal rendering: raw control characters such as ESC (ANSI escape sequences) or CR (line rewrite)
25 * embedded in, for example, a transitive POM's coordinates could otherwise erase or forge log lines - including
26 * the sole integrity WARNING emitted under the default "warn" checksum policy.
27 *
28 * @since 2.0.23
29 */
30 final class LogSanitizer {
31 private LogSanitizer() {}
32
33 /**
34 * Replaces every ISO control character below U+0020 (except LF and TAB) as well as DEL (U+007F) with its
35 * visible {@code \}{@code uXXXX} escape, preserving the evidence while neutralizing terminal escape
36 * sequences. Returns the input instance unchanged (no allocation) when nothing needs escaping; returns
37 * {@code null} for {@code null} input.
38 */
39 static String sanitize(String value) {
40 if (value == null) {
41 return null;
42 }
43 StringBuilder result = null;
44 for (int i = 0; i < value.length(); i++) {
45 char c = value.charAt(i);
46 if ((c < 0x20 && c != '\n' && c != '\t') || c == 0x7f) {
47 if (result == null) {
48 result = new StringBuilder(value.length() + 16);
49 result.append(value, 0, i);
50 }
51 result.append(String.format("\\u%04X", (int) c));
52 } else if (result != null) {
53 result.append(c);
54 }
55 }
56 return result == null ? value : result.toString();
57 }
58 }