Skip to content

Commit 4779608

Browse files
authored
Merge pull request #7 from little-pan/v0.3.29-res-limit
Added "--max-allowed-packet" parameter for limiting input message size
2 parents bada930 + f77e688 commit 4779608

5 files changed

Lines changed: 95 additions & 17 deletions

File tree

src/main/java/org/sqlite/server/SQLiteProcessor.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -594,12 +594,15 @@ protected ByteBuffer getReadBuffer(final int minSize) {
594594
return buf;
595595
}
596596

597-
final int lim = buf.limit();
598-
freeSize = Math.max(freeSize + cap, minSize);
599-
ByteBuffer newBuffer = ByteBuffer.allocate(pos + freeSize);
597+
trace(log, "{}: allocate a new read buffer - pos {}, freeSize {}, request minSize {}",
598+
this, pos, freeSize, minSize);
599+
freeSize = Math.max(freeSize << 1, minSize);
600+
final int newSize = pos + freeSize;
601+
ByteBuffer newBuffer = ByteBuffer.allocate(newSize);
600602
buf.flip();
601603
newBuffer.put(buf);
602-
newBuffer.limit(lim);
604+
// fixbug - dead-loop issue for setting newBuffer limit as buf.limit()
605+
newBuffer.limit(newSize);
603606
return (this.readBuffer = newBuffer);
604607
}
605608

src/main/java/org/sqlite/server/SQLiteServer.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public abstract class SQLiteServer implements AutoCloseable {
7979
public static final int MAX_CONNS_DEFAULT = 50;
8080
public static final int MAX_WORKER_COUNT = 128;
8181
public static final int CONNECT_TIMEOUT_DEFAULT = 30000;
82+
public static final long MAX_ALLOWED_PACKET_DEFAULT = 16L << 20;
8283
// SQLite settings
8384
public static final int BUSY_TIMEOUT_DEFAULT = 50000;
8485
public static final JournalMode JOURNAL_MODE_DEFAULT = JournalMode.WAL;
@@ -126,6 +127,10 @@ public abstract class SQLiteServer implements AutoCloseable {
126127
protected TimestampFunc clockTimestampFunc;
127128
protected TimestampFunc sysdateFunc;
128129

130+
// Resource limit since v0.3.29 2019-12-14
131+
protected long maxAllowedPacket = MAX_ALLOWED_PACKET_DEFAULT;
132+
133+
// Life-cycle states
129134
private final AtomicBoolean inited = new AtomicBoolean(false);
130135
private volatile boolean stopped;
131136

@@ -416,7 +421,9 @@ public void init(String... args) {
416421
this.workerCount = Math.min(MAX_WORKER_COUNT, n);
417422
} else if ("--auth-method".equals(a) || "-A".equals(a)) {
418423
this.authMethod = toLowerEnglish(args[++i]);
419-
} else if ("--help".equals(a) || "-h".equals(a) || "-?".equals(a)) {
424+
} else if ("--max-allowed-packet".equals(a)) {
425+
this.maxAllowedPacket = Long.decode(args[++i]);
426+
} if ("--help".equals(a) || "-h".equals(a) || "-?".equals(a)) {
420427
help = true;
421428
}
422429
}
@@ -773,6 +780,10 @@ public int getMaxConns() {
773780
return this.maxConns;
774781
}
775782

783+
public long getMaxAllowedPacket() {
784+
return maxAllowedPacket;
785+
}
786+
776787
public String getVersion() {
777788
return VERSION;
778789
}
@@ -1003,7 +1014,7 @@ protected String getInitDbHelp() {
10031014
" --journal-mode <mode> SQLite journal mode, default "+JOURNAL_MODE_DEFAULT+"\n"+
10041015
" --synchronous|-S<sync> SQLite synchronous mode, default "+SYNCHRONOUS_DEFAULT+ "\n"+
10051016
" --protocol <pg> SQLite server protocol, default pg\n"+
1006-
" --auth-method|-A<authMethod> Available auth methods("+getAuthMethods()+"), default '"+getAuthDefault()+"'";
1017+
" --auth-method|-A<authMethod> Available auth methods("+getAuthMethods()+"), default "+getAuthDefault();
10071018
}
10081019

10091020
protected String getBootHelp() {
@@ -1020,7 +1031,8 @@ protected String getBootHelp() {
10201031
" --busy-timeout <millis> SQL statement busy timeout, default "+BUSY_TIMEOUT_DEFAULT+"\n"+
10211032
" --journal-mode <mode> SQLite journal mode, default "+JOURNAL_MODE_DEFAULT+"\n"+
10221033
" --synchronous|-S<sync> SQLite synchronous mode, default "+SYNCHRONOUS_DEFAULT+ "\n"+
1023-
" --protocol <pg> SQLite server protocol, default pg";
1034+
" --protocol <pg> SQLite server protocol, default pg\n"+
1035+
" --max-allowed-packet <number> Max allowed packet size, default " + MAX_ALLOWED_PACKET_DEFAULT;
10241036
}
10251037

10261038
protected static void doHelp(int status, String message) {

src/main/java/org/sqlite/server/pg/PgProcessor.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,20 +239,30 @@ protected void process() throws IOException {
239239
| (inBuf.get(4) & 0xFF) << 0;
240240
this.inSize -= 4;
241241
server.trace(log, ">> message: type '{}'(c) {}, len {}", (char)x, x, this.inSize);
242+
243+
// Check max message size for input buffer overflow issue
244+
final long maxAllowedPacket = this.server.getMaxAllowedPacket();
245+
if (this.inSize > maxAllowedPacket && maxAllowedPacket > 0) {
246+
sendErrorResponse("Message sent too big", "53400"/*Configuration_limit_exceeded*/);
247+
enableWrite();
248+
stop();
249+
return;
250+
}
242251
}
243252

244253
// 2. read body
245254
int buffered = inBuf.position() - 5;
246-
if (buffered < inSize) {
247-
inBuf = getReadBuffer(inSize - buffered);
255+
if (buffered < this.inSize) {
256+
inBuf = getReadBuffer(this.inSize - buffered);
248257
n = ch.read(inBuf);
249258
if (n < 0) {
250-
stop();
259+
trace(log, "{}: peer closed", this);
251260
enableWrite();
261+
stop();
252262
return;
253263
}
254264
buffered = inBuf.position() - 5;
255-
if (buffered < inSize) {
265+
if (buffered < this.inSize) {
256266
return;
257267
}
258268
}
@@ -889,13 +899,20 @@ private void sendErrorResponse(SQLException e) throws IOException {
889899
}
890900

891901
private void sendErrorResponse(String message) throws IOException {
902+
sendErrorResponse(message, null);
903+
}
904+
905+
private void sendErrorResponse(String message, String sqlState) throws IOException {
906+
if (sqlState == null) {
907+
// PROTOCOL VIOLATION
908+
sqlState = "08P01";
909+
}
892910
server.trace(log, "Exception: {}", message);
893911
startMessage('E');
894912
write('S');
895913
writeString("ERROR");
896914
write('C');
897-
// PROTOCOL VIOLATION
898-
writeString("08P01");
915+
writeString(sqlState);
899916
write('M');
900917
writeString(message);
901918
sendMessage();

src/test/java/org/sqlite/TestDbBase.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,19 @@ public abstract class TestDbBase extends TestBase {
8181
protected static final String [][] bootArgsList = new String[][] {
8282
{"-D", dataDir, //"--trace-error", //"-T",
8383
"--worker-count", "4", "--max-conns", "50",
84-
"--journal-mode", "wal"
84+
"--journal-mode", "wal", "--max-allowed-packet", "0",
8585
},
8686
{"-D", dataDir, //"--trace-error", //"-T",
8787
"--worker-count", "4", "--max-conns", "50",
88-
"--journal-mode", "delete", "-S", "normal"
88+
"--journal-mode", "delete", "-S", "normal",
8989
},
9090
{"-D", dataDir, //"--trace-error", //"-T",
9191
"--worker-count", "4", "--max-conns", "50",
92-
"--journal-mode", "wal"
92+
"--journal-mode", "wal", "--max-allowed-packet", "0x1000000",
9393
},
9494
{"-D", dataDir, //"--trace-error", //"-T",
9595
"--worker-count", "4", "--max-conns", "50",
96-
"--journal-mode", "delete", "-S", "normal"
96+
"--journal-mode", "delete", "-S", "normal", "--max-allowed-packet", "0x10000",
9797
},
9898
};
9999

@@ -313,6 +313,10 @@ protected DbTestEnv(int envIndex) {
313313
this.simpleQuery = url.contains("preferQueryMode=simple");
314314
}
315315

316+
public long getMaxAllowedPacket() {
317+
return this.server.getMaxAllowedPacket();
318+
}
319+
316320
public int getWorkerCount() {
317321
return this.server.getWorkerCount();
318322
}

src/test/java/org/sqlite/server/SQLiteServerTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
package org.sqlite.server;
1717

1818
import java.sql.Connection;
19+
import java.sql.PreparedStatement;
1920
import java.sql.SQLException;
21+
import java.sql.Statement;
2022

2123
import org.sqlite.TestDbBase;
2224
import org.sqlite.server.util.IoUtils;
@@ -36,6 +38,10 @@ public static void main(String[] args) throws SQLException {
3638
@Override
3739
protected void doTest() throws SQLException {
3840
initdbTest();
41+
42+
maxAllowedPacketTest(1);
43+
maxAllowedPacketTest(2);
44+
maxAllowedPacketTest(10);
3945
}
4046

4147
private void initdbTest() throws SQLException {
@@ -173,4 +179,40 @@ private void initdbTest() throws SQLException {
173179
assertTrue(server.isStopped());
174180
}
175181

182+
private void maxAllowedPacketTest(int times) throws SQLException {
183+
for (int i = 0; i < times; ++i) {
184+
doMaxAllowedPacketTest();
185+
}
186+
}
187+
188+
private void doMaxAllowedPacketTest() throws SQLException {
189+
final long maxPacket = this.currentEnv.getMaxAllowedPacket();
190+
191+
try (Connection conn = getConnection()) {
192+
PreparedStatement ps;
193+
Statement stmt = conn.createStatement();
194+
stmt.executeUpdate("drop table if exists test_blob");
195+
stmt.executeUpdate("create table test_blob(id integer primary key, value blob)");
196+
stmt.close();
197+
198+
ps = conn.prepareStatement("insert into test_blob(value)values(?)");
199+
for (int size: new int[]{
200+
1<<10, 2<<10, 4<<10, 16<< 10, 64<<10, 256<<10,
201+
1<<20, 10<<20, 16<<20, 20<<20 }) {
202+
try {
203+
byte[] blob = new byte[size];
204+
ps.setBytes(1, blob);
205+
ps.executeUpdate();
206+
ps.clearParameters();
207+
} catch (SQLException e) {
208+
final String sqlState = e.getSQLState();
209+
if (maxPacket <= 0L || size < maxPacket || (!sqlState.startsWith("08"))) {
210+
throw e;
211+
}
212+
}
213+
}
214+
ps.close();
215+
}
216+
}
217+
176218
}

0 commit comments

Comments
 (0)