feat: limit max texture width to avoid png bomb

This commit is contained in:
Steven Qiu 2025-06-29 06:41:35 +08:00
parent 16bf9ee659
commit a92c441b1a
No known key found for this signature in database
GPG Key ID: 8ACE9DCFC76F38B9
7 changed files with 44 additions and 7 deletions

View File

@ -163,6 +163,10 @@ class OptionsController extends Controller
->text('max_upload_file_size')->addon('KB')
->hint(trans('options.general.max_upload_file_size.hint', ['size' => ini_get('upload_max_filesize')]));
$form->group('max_texture_width')
->text('max_texture_width')->addon('px')
->hint(trans('options.general.max_texture_width.hint'));
$form->select('player_name_rule')
->option('official', trans('options.general.player_name_rule.official'))
->option('cjk', trans('options.general.player_name_rule.cjk'))

View File

@ -217,9 +217,17 @@ class SkinlibController extends Controller
return json($can->getReason(), 1);
}
$image = imagecreatefrompng($file);
$type = $data['type'];
$size = [imagesx($image), imagesy($image)];
$size = getimagesize($file);
$maxWidth = option('max_texture_width', 8192);
if ($size[0] > $maxWidth) {
$message = trans('skinlib.upload.too-wide', [
'width' => $size[0],
'maxWidth' => $maxWidth
]);
return json($message, 1);
}
if ($size[0] % 64 != 0 || $size[1] % 32 != 0) {
$message = trans('skinlib.upload.invalid-size', [
@ -254,6 +262,7 @@ class SkinlibController extends Controller
}
}
$image = imagecreatefrompng($file);
$imageSanitized = imagecreatetruecolor($size[0], $size[1]);
imagealphablending($imageSanitized, false);
imagesavealpha($imageSanitized, true);

View File

@ -110,7 +110,10 @@ general:
regs_per_ip: Max accounts of one IP
max_upload_file_size:
title: Max Upload Size
hint: "Limit specified in php.ini: :size"
hint: 'Limit specified in php.ini: :size'
max_texture_width:
title: Max Texture Width
hint: Maximum width of uploaded textures, must be an integer multiple of 64
player_name_rule:
title: Player Name Rule
official: Letters, numbers and underscores (Mojang's official rule)
@ -129,8 +132,8 @@ general:
label: Delete invalid textures automatically.
hint: Delete textures records whose file no longer exists from skinlib.
allow_downloading_texture:
title: Downloading Textures
label: Allow users to directly download the source file of a skinlib item.
title: Downloading Textures
label: Allow users to directly download the source file of a skinlib item.
status_code_for_private:
title: HTTP Code for Rejecting Accessing Private Textures
texture_name_regexp:

View File

@ -13,6 +13,7 @@ upload:
private-score-notice: It will spend you more scores for setting it as private. You will be charged :score scores for per KB storage.
invalid-size: Invalid :type file (width :width, height :height)
invalid-hd-skin: Invalid HD skin (width and height should be divisible by 32)
too-wide: The texture is too wide (:widthpx), maximum width allowed is :maxWidthpx
lack-score: You don't have enough score to upload this texture.
repeated: The texture is already uploaded by someone else. You can add it to your closet directly.
success: Texture :name was uploaded successfully.

View File

@ -20,7 +20,7 @@ homepage:
label: 开启后背景不会随页面滚动而滚动
copyright_prefer:
title: 程序版权信息
description: "每种支持的语言都可以对应不同的程序版权信息,如果想要编辑某种特定语言下的版权信息,请在右上角切换至该语言后再提交修改。<b>对于任何恶意修改页面右下角的版权信息(包括不限于删除、修改作者信息、修改链接指向)的用户,作者保留对其追究责任的权利。</b>"
description: '每种支持的语言都可以对应不同的程序版权信息,如果想要编辑某种特定语言下的版权信息,请在右上角切换至该语言后再提交修改。<b>对于任何恶意修改页面右下角的版权信息(包括不限于删除、修改作者信息、修改链接指向)的用户,作者保留对其追究责任的权利。</b>'
copyright_text:
title: 自定义版权文字
description: 自定义版权文字内可使用占位符,<code>{site_name}</code> 将会被自动替换为站点名称,<code>{site_url}</code> 会被替换为站点地址。每种支持的语言都可以对应不同的自定义版权文字,如果想要编辑某种特定语言下的版权文字,请在右上角切换至该语言后再提交修改。
@ -97,7 +97,10 @@ general:
regs_per_ip: 每个 IP 限制注册数
max_upload_file_size:
title: 最大允许上传大小
hint: "PHP 限制::size定义在 php.ini 中。"
hint: 'PHP 限制::size定义在 php.ini 中。'
max_texture_width:
title: 最大允许材质宽度
hint: 允许上传的材质的最大的宽度,必须是 64 的整数倍
player_name_rule:
title: 角色名规则
official: 大小写字母数字下划线Mojang 官方的用户名规则)

View File

@ -12,6 +12,7 @@ upload:
private-score-notice: 私密材质将会消耗更多的积分:每 KB 存储空间 :score 积分
invalid-size: 不是有效的 :type 文件(宽 :width高 :height
invalid-hd-skin: 不是有效的高清皮肤(宽和高不是 32 的整数倍)
too-wide: 材质过宽(:widthpx本站允许的最大宽度为 :maxWidthpx
lack-score: 积分不足
repeated: 已经有人上传过这个材质了,直接添加到衣柜使用吧~
success: 材质 :name 上传成功

View File

@ -303,6 +303,22 @@ class SkinlibControllerTest extends TestCase
'type' => 'steve',
])->assertJsonValidationErrors('public');
// too wide texture
option(['max_texture_width' => 128]);
$this->postJson(route('texture.upload'), [
'name' => 'texture',
'file' => UploadedFile::fake()->image('wide.png', 256, 256),
'type' => 'steve',
'public' => true,
])->assertJson([
'code' => 1,
'message' => trans('skinlib.upload.too-wide', [
'width' => 256,
'maxWidth' => 128,
]),
]);
option(['max_texture_width' => 8192]);
// invalid skin size
$this->postJson(route('texture.upload'), [
'name' => 'texture',