View Javadoc
1   package io.jawk;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * Jawk
6    * ჻჻჻჻჻჻
7    * Copyright (C) 2006 - 2026 MetricsHub
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import java.util.Collection;
26  import java.util.List;
27  import io.jawk.backend.AVM;
28  import io.jawk.backend.SandboxedAVM;
29  import io.jawk.ext.JawkExtension;
30  import io.jawk.intermediate.Address;
31  import io.jawk.util.AwkSettings;
32  import io.jawk.util.ScriptSource;
33  
34  /**
35   * {@link Awk} variant that enforces sandbox restrictions by delegating to the
36   * sandbox-specific tuple and runtime implementations.
37   */
38  public final class SandboxedAwk extends Awk {
39  
40  	/**
41  	 * Creates a sandboxed AWK instance with default settings and no extensions.
42  	 */
43  	public SandboxedAwk() {
44  		super();
45  	}
46  
47  	/**
48  	 * Creates a sandboxed AWK instance with the specified settings.
49  	 *
50  	 * @param settings behavioral configuration for this engine
51  	 */
52  	public SandboxedAwk(AwkSettings settings) {
53  		super(settings);
54  	}
55  
56  	/**
57  	 * Creates a sandboxed AWK instance with the supplied extensions.
58  	 *
59  	 * @param extensions Extension instances to register
60  	 */
61  	public SandboxedAwk(Collection<? extends JawkExtension> extensions) {
62  		super(extensions);
63  	}
64  
65  	/**
66  	 * Creates a sandboxed AWK instance with extensions and settings.
67  	 *
68  	 * @param extensions extension instances
69  	 * @param settings behavioral configuration for this engine
70  	 */
71  	public SandboxedAwk(Collection<? extends JawkExtension> extensions, AwkSettings settings) {
72  		super(extensions, settings);
73  	}
74  
75  	/**
76  	 * Creates a sandboxed AWK instance with the supplied extensions.
77  	 *
78  	 * @param extensions Extension instances to register
79  	 */
80  	@SafeVarargs
81  	public SandboxedAwk(JawkExtension... extensions) {
82  		super(extensions);
83  	}
84  
85  	@Override
86  	public AwkProgram compile(List<ScriptSource> scripts, boolean disableOptimizeParam) throws java.io.IOException {
87  		return compileProgram(scripts, disableOptimizeParam, new SandboxedCompiledAwkProgram());
88  	}
89  
90  	@Override
91  	public AwkExpression compileExpression(String expression, boolean disableOptimizeParam) throws java.io.IOException {
92  		return compileExpression(expression, disableOptimizeParam, new SandboxedCompiledAwkExpression());
93  	}
94  
95  	@Override
96  	protected boolean isSourceIncludeAllowed() {
97  		return false;
98  	}
99  
100 	@Override
101 	public AVM createAvm() {
102 		return createAvm(getSettings());
103 	}
104 
105 	@Override
106 	public AVM createAvm(boolean profilingEnabled) {
107 		return createAvm(getSettings(), profilingEnabled);
108 	}
109 
110 	@Override
111 	protected AVM createAvm(AwkSettings settingsParam) {
112 		return createAvm(settingsParam, false);
113 	}
114 
115 	@Override
116 	protected AVM createAvm(AwkSettings settingsParam, boolean profilingEnabled) {
117 		return new SandboxedAVM(settingsParam, getExtensionInstances(), profilingEnabled);
118 	}
119 }
120 
121 final class SandboxedCompiledAwkProgram extends AwkProgram {
122 	private static final long serialVersionUID = 1L;
123 
124 	@Override
125 	public void printToFile(int numExprs, boolean append) {
126 		deny("Output redirection is disabled in sandbox mode");
127 	}
128 
129 	@Override
130 	public void printToPipe(int numExprs) {
131 		deny("Command execution through pipelines is disabled in sandbox mode");
132 	}
133 
134 	@Override
135 	public void printfToFile(int numExprs, boolean append) {
136 		deny("Output redirection is disabled in sandbox mode");
137 	}
138 
139 	@Override
140 	public void printfToPipe(int numExprs) {
141 		deny("Command execution through pipelines is disabled in sandbox mode");
142 	}
143 
144 	@Override
145 	public void system() {
146 		deny("system() is disabled in sandbox mode");
147 	}
148 
149 	@Override
150 	public void useAsCommandInput(Address noRecordAddress) {
151 		deny("Command execution through pipelines is disabled in sandbox mode");
152 	}
153 
154 	@Override
155 	public void useAsFileInput(Address noRecordAddress) {
156 		deny("Input redirection is disabled in sandbox mode");
157 	}
158 
159 	@Override
160 	public void assignARGC() {
161 		deny("Assigning to ARGC is disabled in sandbox mode");
162 	}
163 
164 	@Override
165 	public void argcOffset(int offset) {
166 		// no-op: keep argcOffset at NULL_OFFSET; AVM.getARGC() returns the
167 		// command-line argument count when ARGC is not materialized.
168 	}
169 
170 	@Override
171 	public void argvOffset(int offset) {
172 		// no-op: keep argvOffset at NULL_OFFSET; AVM.getARGV() returns a
173 		// synthetic AssocArray when ARGV is not materialized.
174 	}
175 
176 	private static void deny(String message) {
177 		throw new AwkSandboxException(message);
178 	}
179 }
180 
181 final class SandboxedCompiledAwkExpression extends AwkExpression {
182 	private static final long serialVersionUID = 1L;
183 
184 	@Override
185 	public void printToFile(int numExprs, boolean append) {
186 		deny("Output redirection is disabled in sandbox mode");
187 	}
188 
189 	@Override
190 	public void printToPipe(int numExprs) {
191 		deny("Command execution through pipelines is disabled in sandbox mode");
192 	}
193 
194 	@Override
195 	public void printfToFile(int numExprs, boolean append) {
196 		deny("Output redirection is disabled in sandbox mode");
197 	}
198 
199 	@Override
200 	public void printfToPipe(int numExprs) {
201 		deny("Command execution through pipelines is disabled in sandbox mode");
202 	}
203 
204 	@Override
205 	public void system() {
206 		deny("system() is disabled in sandbox mode");
207 	}
208 
209 	@Override
210 	public void useAsCommandInput(Address noRecordAddress) {
211 		deny("Command execution through pipelines is disabled in sandbox mode");
212 	}
213 
214 	@Override
215 	public void useAsFileInput(Address noRecordAddress) {
216 		deny("Input redirection is disabled in sandbox mode");
217 	}
218 
219 	@Override
220 	public void assignARGC() {
221 		deny("Assigning to ARGC is disabled in sandbox mode");
222 	}
223 
224 	@Override
225 	public void argcOffset(int offset) {
226 		// no-op: keep argcOffset at NULL_OFFSET; AVM.getARGC() returns the
227 		// command-line argument count when ARGC is not materialized.
228 	}
229 
230 	@Override
231 	public void argvOffset(int offset) {
232 		// no-op: keep argvOffset at NULL_OFFSET; AVM.getARGV() returns a
233 		// synthetic AssocArray when ARGV is not materialized.
234 	}
235 
236 	private static void deny(String message) {
237 		throw new AwkSandboxException(message);
238 	}
239 }