fix: Исправлены критические баги HIGH приоритета

- Исправлены утечки ResultSet в SQLiteDatabaseManager и PostgreSQLDatabaseManager
  Все ResultSet теперь закрываются в try-with-resources блоках
- Добавлена валидация входных данных reason в ReportCommand
  Проверка на пустую строку и максимальную длину 500 символов
- Исправлен integer overflow в PaginationUtil.calculateStartIndex
  Добавлена проверка на переполнение при умножении page * pageSize
- Добавлены null-проверки в ConfigManager.getMessage
  Защита от NPE при null элементах в массиве replacements
This commit is contained in:
loki 2026-04-09 00:34:12 +02:00
parent 4f1572c9df
commit bf65a1f9ae
5 changed files with 93 additions and 59 deletions

View file

@ -58,6 +58,17 @@ public class ReportCommand implements CommandExecutor, TabCompleter {
String targetName = args[0];
String reason = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
// Validate reason
if (reason.trim().isEmpty()) {
player.sendMessage(plugin.getConfigManager().getMessage("usage"));
return true;
}
if (reason.length() > 500) {
player.sendMessage("§cПричина слишком длинная! Максимум 500 символов.");
return true;
}
return handleReport(player, targetName, reason);
}

View file

@ -63,8 +63,13 @@ public class ConfigManager {
public String getMessage(String key, String... replacements) {
String message = getMessage(key);
if (replacements == null || replacements.length == 0) {
return message;
}
for (int i = 0; i < replacements.length - 1; i += 2) {
message = message.replace(replacements[i], replacements[i + 1]);
if (replacements[i] != null && replacements[i + 1] != null) {
message = message.replace(replacements[i], replacements[i + 1]);
}
}
return message;
}

View file

@ -118,9 +118,10 @@ public class PostgreSQLDatabaseManager implements DatabaseManager {
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, targetUuid.toString());
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
reports.add(mapReport(rs));
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
reports.add(mapReport(rs));
}
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Failed to get reports for target", e);
@ -135,8 +136,8 @@ public class PostgreSQLDatabaseManager implements DatabaseManager {
List<Report> reports = new ArrayList<>();
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
ResultSet rs = stmt.executeQuery();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
reports.add(mapReport(rs));
}
@ -154,9 +155,10 @@ public class PostgreSQLDatabaseManager implements DatabaseManager {
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, targetUuid.toString());
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
return rs.getInt(1);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return rs.getInt(1);
}
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Failed to get report count", e);
@ -173,9 +175,10 @@ public class PostgreSQLDatabaseManager implements DatabaseManager {
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, reporterUuid.toString());
stmt.setString(2, targetUuid.toString());
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
return rs.getInt(1) > 0;
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return rs.getInt(1) > 0;
}
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Failed to check if reported", e);
@ -193,9 +196,10 @@ public class PostgreSQLDatabaseManager implements DatabaseManager {
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, pageSize);
stmt.setInt(2, page * pageSize);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
reports.add(mapReport(rs));
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
reports.add(mapReport(rs));
}
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Failed to get paginated reports", e);
@ -209,8 +213,8 @@ public class PostgreSQLDatabaseManager implements DatabaseManager {
String sql = "SELECT COUNT(*) FROM reports";
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
ResultSet rs = stmt.executeQuery();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return rs.getInt(1);
}

View file

@ -97,11 +97,12 @@ public class SQLiteDatabaseManager implements DatabaseManager {
String sql = "SELECT * FROM reports WHERE target_uuid = ? ORDER BY created_at DESC";
List<Report> reports = new ArrayList<>();
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
try (PreparedStatement stmt = connection.prepareStatement(sql);) {
stmt.setString(1, targetUuid.toString());
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
reports.add(mapReport(rs));
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
reports.add(mapReport(rs));
}
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Failed to get reports for target", e);
@ -115,8 +116,8 @@ public class SQLiteDatabaseManager implements DatabaseManager {
String sql = "SELECT * FROM reports ORDER BY created_at DESC";
List<Report> reports = new ArrayList<>();
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
ResultSet rs = stmt.executeQuery();
try (PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
reports.add(mapReport(rs));
}
@ -133,9 +134,10 @@ public class SQLiteDatabaseManager implements DatabaseManager {
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, targetUuid.toString());
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
return rs.getInt(1);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return rs.getInt(1);
}
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Failed to get report count", e);
@ -151,9 +153,10 @@ public class SQLiteDatabaseManager implements DatabaseManager {
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, reporterUuid.toString());
stmt.setString(2, targetUuid.toString());
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
return rs.getInt(1) > 0;
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return rs.getInt(1) > 0;
}
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Failed to check if reported", e);
@ -170,9 +173,10 @@ public class SQLiteDatabaseManager implements DatabaseManager {
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setInt(1, pageSize);
stmt.setInt(2, page * pageSize);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
reports.add(mapReport(rs));
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
reports.add(mapReport(rs));
}
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Failed to get paginated reports", e);
@ -185,8 +189,8 @@ public class SQLiteDatabaseManager implements DatabaseManager {
public int getTotalReportCount() {
String sql = "SELECT COUNT(*) FROM reports";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
ResultSet rs = stmt.executeQuery();
try (PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return rs.getInt(1);
}

View file

@ -3,11 +3,21 @@ package dev.loki.lorep.util;
public class PaginationUtil {
public static int calculateTotalPages(int totalItems, int pageSize) {
if (pageSize <= 0) {
throw new IllegalArgumentException("pageSize must be positive");
}
if (totalItems <= 0) return 1;
return (int) Math.ceil((double) totalItems / pageSize);
}
public static int calculateStartIndex(int page, int pageSize) {
if (page < 0 || pageSize <= 0) {
return 0;
}
// Check for overflow
if (page > Integer.MAX_VALUE / pageSize) {
return Integer.MAX_VALUE;
}
return page * pageSize;
}