Skip to content

Commit 65ad57a

Browse files
Jupeyyheinrich5991
authored andcommitted
Change from pnglite to libpng for PNG reading
This is desirable mainly because libpng is maintained and pnglite is not. pnglite was last updated in 2007 (15 years ago) and probably has a lot of security vulnerabilities. libpng is an actively maintained library also used by browsers like Firefox or Chromium, so it's less likely to contain security vulnerabilities, also it's more likely to be packaged by Linux distributions.
1 parent fad8afc commit 65ad57a

17 files changed

+543
-1355
lines changed

.github/workflows/build.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ jobs:
5858
run: |
5959
sudo apt-get update -y
6060
sudo apt-get upgrade -y
61-
sudo apt-get install pkg-config cmake ninja-build libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev libvulkan-dev glslang-tools spirv-tools libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libx264-dev valgrind -y
61+
sudo apt-get install pkg-config cmake ninja-build libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev libvulkan-dev glslang-tools spirv-tools libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libx264-dev libpng-dev valgrind -y
6262
6363
- name: Prepare Linux (non-fancy)
6464
if: ${{ contains(matrix.os, 'ubuntu') && !matrix.fancy }}

CMakeLists.txt

+16-8
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ endif()
545545
find_package(Ogg)
546546
find_package(Opus)
547547
find_package(Opusfile)
548-
find_package(Pnglite)
548+
find_package(PNG)
549549
find_package(PythonInterp 3)
550550
find_package(SDL2)
551551
find_package(SQLite3)
@@ -631,7 +631,7 @@ show_dependency_status("Ogg" OGG)
631631
show_dependency_status("OpenSSL Crypto" CRYPTO)
632632
show_dependency_status("Opus" OPUS)
633633
show_dependency_status("Opusfile" OPUSFILE)
634-
show_dependency_status("Pnglite" PNGLITE)
634+
show_dependency_status("PNG" PNG)
635635
show_dependency_status("PythonInterp" PYTHONINTERP)
636636
show_dependency_status("SDL2" SDL2)
637637
show_dependency_status("SQLite3" SQLite3)
@@ -680,6 +680,9 @@ if(DISCORD_DYNAMIC)
680680
message(SEND_ERROR "You must enable the DISCORD flag if you want to link the Discord SDK")
681681
endif()
682682
endif()
683+
if(NOT(PNG_FOUND))
684+
message(SEND_ERROR "You must install libpng to compile DDNet")
685+
endif()
683686
if(CLIENT AND NOT(FREETYPE_FOUND))
684687
message(SEND_ERROR "You must install Freetype to compile the ${CMAKE_PROJECT_NAME} client")
685688
endif()
@@ -1562,6 +1565,7 @@ set(COPY_FILES
15621565
${CURL_COPY_FILES}
15631566
${FREETYPE_COPY_FILES}
15641567
${OPUSFILE_COPY_FILES}
1568+
${PNG_COPY_FILES}
15651569
${SDL2_COPY_FILES}
15661570
${SQLite3_COPY_FILES}
15671571
${FFMPEG_COPY_FILES}
@@ -1755,6 +1759,8 @@ set_src(ENGINE_SHARED GLOB_RECURSE src/engine/shared
17551759
http.h
17561760
huffman.cpp
17571761
huffman.h
1762+
image_loader.cpp
1763+
image_loader.h
17581764
image_manipulation.cpp
17591765
image_manipulation.h
17601766
jobs.cpp
@@ -1868,6 +1874,7 @@ set(LIBS
18681874
${CURL_LIBRARIES}
18691875
${SQLite3_LIBRARIES}
18701876
${WEBSOCKETS_LIBRARIES}
1877+
${PNG_LIBRARIES}
18711878
${ZLIB_LIBRARIES}
18721879
${PLATFORM_LIBS}
18731880
# Add pthreads (on non-Windows) at the end, so that other libraries can depend
@@ -1877,6 +1884,7 @@ set(LIBS
18771884

18781885
# Targets
18791886
add_library(engine-shared EXCLUDE_FROM_ALL OBJECT ${ENGINE_INTERFACE} ${ENGINE_SHARED} ${ENGINE_UUID_SHARED} ${BASE})
1887+
target_include_directories(engine-shared PRIVATE ${PNG_INCLUDE_DIRS})
18801888
add_library(game-shared EXCLUDE_FROM_ALL OBJECT ${GAME_SHARED} ${GAME_GENERATED_SHARED})
18811889
list(APPEND TARGETS_OWN engine-shared game-shared)
18821890

@@ -2102,14 +2110,14 @@ if(CLIENT)
21022110
)
21032111
set(CLIENT_SRC ${ENGINE_CLIENT} ${PLATFORM_CLIENT} ${GAME_CLIENT} ${GAME_EDITOR} ${GAME_GENERATED_CLIENT})
21042112

2105-
set(DEPS_CLIENT ${DEPS} ${GLEW_DEP} ${PNGLITE_DEP} ${WAVPACK_DEP})
2113+
set(DEPS_CLIENT ${DEPS} ${GLEW_DEP} ${WAVPACK_DEP})
21062114

21072115
# Libraries
21082116
set(LIBS_CLIENT
21092117
${LIBS}
21102118
${FREETYPE_LIBRARIES}
21112119
${GLEW_LIBRARIES}
2112-
${PNGLITE_LIBRARIES}
2120+
${PNG_LIBRARIES}
21132121
${SDL2_LIBRARIES}
21142122
${WAVPACK_LIBRARIES}
21152123
${FFMPEG_LIBRARIES}
@@ -2185,7 +2193,7 @@ if(CLIENT)
21852193
${OGG_INCLUDE_DIRS}
21862194
${OPUSFILE_INCLUDE_DIRS}
21872195
${OPUS_INCLUDE_DIRS}
2188-
${PNGLITE_INCLUDE_DIRS}
2196+
${PNG_INCLUDE_DIRS}
21892197
${SDL2_INCLUDE_DIRS}
21902198
${WAVPACK_INCLUDE_DIRS}
21912199
${FFMPEG_INCLUDE_DIRS}
@@ -2343,6 +2351,7 @@ if(SERVER)
23432351
# Libraries
23442352
set(LIBS_SERVER
23452353
${LIBS}
2354+
${PNG_LIBRARIES}
23462355
${MYSQL_LIBRARIES}
23472356
${TARGET_ANTIBOT}
23482357
${MINIUPNPC_LIBRARIES}
@@ -2361,6 +2370,7 @@ if(SERVER)
23612370
$<TARGET_OBJECTS:game-shared>
23622371
)
23632372
target_link_libraries(${TARGET_SERVER} ${LIBS_SERVER})
2373+
target_include_directories(${TARGET_SERVER} PRIVATE ${PNG_INCLUDE_DIRS})
23642374
list(APPEND TARGETS_OWN ${TARGET_SERVER})
23652375
list(APPEND TARGETS_LINK ${TARGET_SERVER})
23662376

@@ -2413,9 +2423,7 @@ if(TOOLS)
24132423
set(TOOL_DEPS ${DEPS})
24142424
set(TOOL_LIBS ${LIBS})
24152425
if(TOOL MATCHES "^(dilate|map_convert_07|map_optimize|map_extract|map_replace_image)$")
2416-
list(APPEND TOOL_DEPS ${PNGLITE_DEP})
2417-
list(APPEND TOOL_LIBS ${PNGLITE_LIBRARIES})
2418-
list(APPEND TOOL_INCLUDE_DIRS ${PNGLITE_INCLUDE_DIRS})
2426+
list(APPEND TOOL_INCLUDE_DIRS ${PNG_INCLUDE_DIRS})
24192427
endif()
24202428
if(TOOL MATCHES "^config_")
24212429
list(APPEND EXTRA_TOOL_SRC "src/tools/config_common.h")

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ RUN apt-get update && apt-get install -y mingw-w64 \
1111
libglew-dev \
1212
libogg-dev \
1313
libopus-dev \
14-
libpnglite-dev \
14+
libpng-dev \
1515
libwavpack-dev \
1616
libopusfile-dev \
1717
libsdl2-dev \

README.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Dependencies on Linux / macOS
3434

3535
You can install the required libraries on your system, `touch CMakeLists.txt` and CMake will use the system-wide libraries by default. You can install all required dependencies and CMake on Debian or Ubuntu like this:
3636

37-
sudo apt install build-essential cmake git google-mock libcurl4-openssl-dev libssl-dev libfreetype6-dev libglew-dev libnotify-dev libogg-dev libopus-dev libopusfile-dev libpnglite-dev libsdl2-dev libsqlite3-dev libwavpack-dev python libx264-dev libavfilter-dev libavdevice-dev libavformat-dev libavcodec-extra libavutil-dev libvulkan-dev glslang-tools spirv-tools
37+
sudo apt install build-essential cmake git google-mock libcurl4-openssl-dev libssl-dev libfreetype6-dev libglew-dev libnotify-dev libogg-dev libopus-dev libopusfile-dev libpnglite-dev libsdl2-dev libsqlite3-dev libwavpack-dev python libx264-dev libavfilter-dev libavdevice-dev libavformat-dev libavcodec-extra libavutil-dev libvulkan-dev glslang-tools spirv-tools libpng-dev
3838

3939
On older distributions like Ubuntu 18.04 don't install `google-mock`, but instead set `-DDOWNLOAD_GTEST=ON` when building to get a more recent gtest/gmock version.
4040

@@ -44,9 +44,7 @@ Or on CentOS, RedHat and AlmaLinux like this:
4444

4545
Or on Arch Linux like this:
4646

47-
sudo pacman -S --needed base-devel cmake curl freetype2 git glew gmock libnotify opusfile python sdl2 sqlite wavpack x264 ffmpeg vulkan-icd-loader vulkan-headers glslang spirv-tools
48-
49-
There is an [AUR package for pnglite](https://aur.archlinux.org/packages/pnglite/). For instructions on installing it, see [AUR packages installation instructions on ArchWiki](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
47+
sudo pacman -S --needed base-devel cmake curl freetype2 git glew gmock libnotify opusfile python sdl2 sqlite wavpack x264 ffmpeg vulkan-icd-loader vulkan-headers glslang spirv-tools libpng
5048

5149
On macOS you can use [homebrew](https://brew.sh/) to install build dependencies like this:
5250

cmake/FindPNG.cmake

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
if(NOT PREFER_BUNDLED_LIBS)
2+
set(CMAKE_MODULE_PATH ${ORIGINAL_CMAKE_MODULE_PATH})
3+
find_package(PNG)
4+
set(CMAKE_MODULE_PATH ${OWN_CMAKE_MODULE_PATH})
5+
if(PNG_FOUND)
6+
set(PNG_BUNDLED OFF)
7+
set(PNG_DEP)
8+
endif()
9+
endif()
10+
11+
if(NOT PNG_FOUND)
12+
set_extra_dirs_lib(PNG png)
13+
find_library(PNG_LIBRARY
14+
NAMES png16 libpng16 libpng16-16 png16-16
15+
HINTS ${HINTS_PNG_LIBDIR} ${PC_PNG_LIBDIR} ${PC_PNG_LIBRARY_DIRS}
16+
PATHS ${PATHS_PNG_LIBDIR}
17+
${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
18+
)
19+
20+
set_extra_dirs_include(PNG png "${PNG_LIBRARY}")
21+
find_path(PNG_INCLUDEDIR
22+
NAMES png.h
23+
HINTS ${HINTS_PNG_INCLUDEDIR} ${PC_PNG_INCLUDEDIR} ${PC_PNG_INCLUDE_DIRS}
24+
PATHS ${PATHS_PNG_INCLUDEDIR}
25+
${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
26+
)
27+
28+
mark_as_advanced(PNG_LIBRARY PNG_INCLUDEDIR)
29+
30+
if(PNG_LIBRARY AND PNG_INCLUDEDIR)
31+
include(FindPackageHandleStandardArgs)
32+
find_package_handle_standard_args(PNG DEFAULT_MSG PNG_LIBRARY PNG_INCLUDEDIR)
33+
34+
set(PNG_LIBRARIES ${PNG_LIBRARY})
35+
set(PNG_INCLUDE_DIRS ${PNG_INCLUDEDIR})
36+
endif()
37+
endif()
38+
39+
if(PNG_FOUND)
40+
is_bundled(PNG_BUNDLED "${PNG_LIBRARY}")
41+
if(PNG_BUNDLED AND TARGET_OS STREQUAL "windows")
42+
set(PNG_COPY_FILES "${EXTRA_PNG_LIBDIR}/libpng16-16.dll")
43+
else()
44+
set(PNG_COPY_FILES)
45+
endif()
46+
endif()

cmake/FindPnglite.cmake

-46
This file was deleted.

src/engine/client/graphics_threaded.cpp

+43-50
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
#include <base/system.h>
1212

13-
#include <pnglite.h>
13+
#include <engine/shared/image_loader.h>
1414

1515
#include <engine/console.h>
1616
#include <engine/graphics.h>
@@ -135,8 +135,6 @@ CGraphics_Threaded::CGraphics_Threaded()
135135

136136
m_RenderEnable = true;
137137
m_DoScreenshot = false;
138-
139-
png_init(0, 0);
140138
}
141139

142140
void CGraphics_Threaded::ClipEnable(int x, int y, int w, int h)
@@ -627,54 +625,49 @@ bool CGraphics_Threaded::UpdateTextTexture(CTextureHandle TextureID, int x, int
627625
int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int StorageType)
628626
{
629627
char aCompleteFilename[IO_MAX_PATH_LENGTH];
630-
631-
// open file for reading
632628
IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, StorageType, aCompleteFilename, sizeof(aCompleteFilename));
633-
if(!File)
629+
if(File)
634630
{
635-
dbg_msg("game/png", "failed to open file. filename='%s'", pFilename);
636-
return 0;
637-
}
631+
io_seek(File, 0, IOSEEK_END);
632+
unsigned int FileSize = io_tell(File);
633+
io_seek(File, 0, IOSEEK_START);
638634

639-
png_t Png;
640-
int Error = png_open_read(&Png, 0, File);
641-
if(Error != PNG_NO_ERROR)
642-
{
643-
dbg_msg("game/png", "failed to open file. filename='%s', pnglite: %s", aCompleteFilename, png_error_string(Error));
644-
io_close(File);
645-
return 0;
646-
}
635+
TImageByteBuffer ByteBuffer;
636+
SImageByteBuffer ImageByteBuffer(&ByteBuffer);
647637

648-
if(Png.depth != 8 || (Png.color_type != PNG_TRUECOLOR && Png.color_type != PNG_TRUECOLOR_ALPHA))
649-
{
650-
dbg_msg("game/png", "invalid format. filename='%s'", aCompleteFilename);
651-
io_close(File);
652-
return 0;
653-
}
638+
ByteBuffer.resize(FileSize);
639+
io_read(File, &ByteBuffer.front(), FileSize);
654640

655-
unsigned char *pBuffer = (unsigned char *)malloc((size_t)Png.width * Png.height * Png.bpp);
656-
Error = png_get_data(&Png, pBuffer);
657-
if(Error != PNG_NO_ERROR)
658-
{
659-
dbg_msg("game/png", "failed to read image. filename='%s', pnglite: %s", aCompleteFilename, png_error_string(Error));
660-
free(pBuffer);
661641
io_close(File);
662-
return 0;
663-
}
664-
io_close(File);
665642

666-
pImg->m_Width = Png.width;
667-
pImg->m_Height = Png.height;
668-
if(Png.color_type == PNG_TRUECOLOR)
669-
pImg->m_Format = CImageInfo::FORMAT_RGB;
670-
else if(Png.color_type == PNG_TRUECOLOR_ALPHA)
671-
pImg->m_Format = CImageInfo::FORMAT_RGBA;
643+
uint8_t *pImgBuffer = NULL;
644+
EImageFormat ImageFormat;
645+
if(::LoadPNG(ImageByteBuffer, pFilename, pImg->m_Width, pImg->m_Height, pImgBuffer, ImageFormat))
646+
{
647+
pImg->m_pData = pImgBuffer;
648+
649+
if(ImageFormat == IMAGE_FORMAT_RGB) // ignore_convention
650+
pImg->m_Format = CImageInfo::FORMAT_RGB;
651+
else if(ImageFormat == IMAGE_FORMAT_RGBA) // ignore_convention
652+
pImg->m_Format = CImageInfo::FORMAT_RGBA;
653+
else
654+
{
655+
free(pImgBuffer);
656+
return 0;
657+
}
658+
}
659+
else
660+
{
661+
dbg_msg("game/png", "image had unsupported image format. filename='%s'", pFilename);
662+
return 0;
663+
}
664+
}
672665
else
673666
{
674-
free(pBuffer);
667+
dbg_msg("game/png", "failed to open file. filename='%s'", pFilename);
675668
return 0;
676669
}
677-
pImg->m_pData = pBuffer;
670+
678671
return 1;
679672
}
680673

@@ -806,21 +799,21 @@ bool CGraphics_Threaded::ScreenshotDirect()
806799
{
807800
// find filename
808801
char aWholePath[1024];
809-
png_t Png;
810802

811803
IOHANDLE File = m_pStorage->OpenFile(m_aScreenshotName, IOFLAG_WRITE, IStorage::TYPE_SAVE, aWholePath, sizeof(aWholePath));
812-
if(!File)
804+
if(File)
813805
{
814-
dbg_msg("game/screenshot", "failed to open file. filename='%s'", aWholePath);
815-
}
816-
else
817-
{
818-
// save png
819806
char aBuf[256];
820807
str_format(aBuf, sizeof(aBuf), "saved screenshot to '%s'", aWholePath);
821-
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, ColorRGBA(1.0f, 0.6f, 0.3f, 1.0f));
822-
png_open_write(&Png, 0, File);
823-
png_set_data(&Png, Image.m_Width, Image.m_Height, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)Image.m_pData);
808+
809+
// save png
810+
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, ColorRGBA{1.0f, 0.6f, 0.3f, 1.0f});
811+
812+
TImageByteBuffer ByteBuffer;
813+
SImageByteBuffer ImageByteBuffer(&ByteBuffer);
814+
815+
if(SavePNG(IMAGE_FORMAT_RGBA, (const uint8_t *)Image.m_pData, ImageByteBuffer, Image.m_Width, Image.m_Height))
816+
io_write(File, &ByteBuffer.front(), ByteBuffer.size());
824817
io_close(File);
825818
}
826819

src/engine/external/pnglite/VERSION.txt

-1
This file was deleted.

0 commit comments

Comments
 (0)