Skip to content

Commit 7a88bf5

Browse files
author
Nikita Siniachenko
committed
fixed issues
1 parent 7386f8e commit 7a88bf5

File tree

6 files changed

+336
-351
lines changed

6 files changed

+336
-351
lines changed

runtime-light/k2-platform/k2-api.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,12 @@ inline size_t stderr_write(size_t data_len, const void* data) noexcept {
192192
return k2_stderr_write(data_len, data);
193193
}
194194

195-
inline size_t read(k2::descriptor descriptor, size_t buf_len, void* buf) noexcept {
196-
return k2_read(descriptor, buf_len, buf);
195+
inline size_t read(k2::descriptor descriptor, std::span<std::byte> buffer) noexcept {
196+
return k2_read(descriptor, buffer.size(), static_cast<void*>(buffer.data()));
197197
}
198198

199-
inline size_t pread(k2::descriptor descriptor, size_t buf_len, void* buf, off_t offset) noexcept {
200-
return k2_pread(descriptor, buf_len, buf, offset);
199+
inline size_t pread(k2::descriptor descriptor, std::span<std::byte> buffer, off_t offset) noexcept {
200+
return k2_pread(descriptor, buffer.size(), static_cast<void*>(buffer.data()), offset);
201201
}
202202

203203
inline void please_shutdown(k2::descriptor descriptor) noexcept {
Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
//
2+
// Created by nsinyachenko on 24.10.25.
3+
//
4+
5+
#include "runtime-light/stdlib/file/file-system-functions.h"
6+
7+
static constexpr int64_t IMAGETYPE_UNKNOWN = 0;
8+
static constexpr int64_t IMAGETYPE_GIF = 1;
9+
static constexpr int64_t IMAGETYPE_JPEG = 2;
10+
static constexpr int64_t IMAGETYPE_PNG = 3;
11+
static constexpr int64_t IMAGETYPE_SWF = 4;
12+
static constexpr int64_t IMAGETYPE_PSD = 5;
13+
static constexpr int64_t IMAGETYPE_BMP = 6;
14+
static constexpr int64_t IMAGETYPE_TIFF_II = 7;
15+
static constexpr int64_t IMAGETYPE_TIFF_MM = 8;
16+
static constexpr int64_t IMAGETYPE_JPC = 9;
17+
static constexpr int64_t IMAGETYPE_JPEG2000 = 9;
18+
static constexpr int64_t IMAGETYPE_JP2 = 10;
19+
20+
static constexpr std::array<char, 3> php_sig_gif = {'G', 'I', 'F'};
21+
static constexpr std::array<char, 3> php_sig_jpg = {(char)0xff, (char)0xd8, (char)0xff};
22+
static constexpr std::array<char, 8> php_sig_png = {(char)0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
23+
static constexpr std::array<char, 4> php_sig_jpc = {(char)0xff, 0x4f, (char)0xff, 0x51};
24+
static constexpr std::array<char, 12> php_sig_jp2 = {0x00, 0x00, 0x00, 0x0c, 'j', 'P', ' ', ' ', 0x0d, 0x0a, (char)0x87, 0x0a};
25+
26+
static constexpr std::array<std::string_view, 11> mime_type_string = {
27+
"", "image/gif", "image/jpeg", "image/png", "application/x-shockwave-flash",
28+
"image/psd", "image/x-ms-bmp", "image/tiff", "image/tiff", "application/octet-stream",
29+
"image/jp2"};
30+
31+
static constexpr int M_SOF0 = 0xC0;
32+
static constexpr int M_SOF1 = 0xC1;
33+
static constexpr int M_SOF2 = 0xC2;
34+
static constexpr int M_SOF3 = 0xC3;
35+
static constexpr int M_SOF5 = 0xC5;
36+
static constexpr int M_SOF6 = 0xC6;
37+
static constexpr int M_SOF7 = 0xC7;
38+
static constexpr int M_SOF9 = 0xC9;
39+
static constexpr int M_SOF10 = 0xCA;
40+
static constexpr int M_SOF11 = 0xCB;
41+
static constexpr int M_SOF13 = 0xCD;
42+
static constexpr int M_SOF14 = 0xCE;
43+
static constexpr int M_SOF15 = 0xCF;
44+
static constexpr int M_EOI = 0xD9;
45+
static constexpr int M_SOS = 0xDA;
46+
static constexpr int M_COM = 0xFE;
47+
48+
static constexpr int M_PSEUDO = 0xFFD8;
49+
50+
inline mixed f$getimagesize(const string& name) {
51+
// TODO implement k2_fstat, with fd as parameter !!!
52+
struct stat stat_buf;
53+
if (k2_stat(name.c_str(), name.size(), &stat_buf) != k2::errno_ok) {
54+
return false;
55+
}
56+
57+
auto sync_res{from_mixed<class_instance<kphp::fs::sync_resource>>(f$fopen(name, READ_MODE), {})};
58+
if (sync_res.is_null()) {
59+
return false;
60+
}
61+
auto f = sync_res.get();
62+
63+
if (!S_ISREG(stat_buf.st_mode)) {
64+
kphp::log::warning("Regular file expected as first argument in function getimagesize, \"%s\" is given", name.c_str());
65+
return false;
66+
}
67+
68+
constexpr size_t min_size = 3 * 256 + 64;
69+
std::array<unsigned char, min_size> buf;
70+
size_t size = stat_buf.st_size;
71+
size_t read_size = min_size;
72+
if (size < min_size) {
73+
read_size = size;
74+
}
75+
std::span<unsigned char> buf_span(buf.begin(), min_size);
76+
77+
if (read_size < 12) {
78+
return false;
79+
}
80+
std::expected<size_t, int32_t> read_res = read_safe(f, std::as_writable_bytes(buf_span));
81+
if (!read_res || *read_res < read_size) {
82+
return false;
83+
}
84+
85+
int width = 0;
86+
int height = 0;
87+
int bits = 0;
88+
int channels = 0;
89+
int type = IMAGETYPE_UNKNOWN;
90+
switch (buf[0]) {
91+
case 'G': // gif
92+
if (!std::strncmp((const char*)buf.begin(), php_sig_gif.begin(), sizeof(php_sig_gif))) {
93+
type = IMAGETYPE_GIF;
94+
width = buf[6] | (buf[7] << 8);
95+
height = buf[8] | (buf[9] << 8);
96+
bits = buf[10] & 0x80 ? (buf[10] & 0x07) + 1 : 0;
97+
channels = 3;
98+
} else {
99+
return false;
100+
}
101+
break;
102+
case 0xff: // jpg or jpc
103+
if (!std::strncmp((const char*)buf.begin(), php_sig_jpg.begin(), sizeof(php_sig_jpg))) {
104+
type = IMAGETYPE_JPEG;
105+
106+
unsigned char* image = (unsigned char*)RuntimeAllocator::get().alloc_script_memory(size);
107+
if (image == nullptr) {
108+
kphp::log::warning("Not enough memory to process file \"%s\" in getimagesize", name.c_str());
109+
return false;
110+
}
111+
memcpy(image, buf.begin(), read_size);
112+
113+
std::span<unsigned char> image_span(image + read_size, size - read_size);
114+
read_res = read_safe(f, std::as_writable_bytes(image_span));
115+
if (!read_res || *read_res < size - read_size) {
116+
RuntimeAllocator::get().free_script_memory(image, size);
117+
return false;
118+
}
119+
120+
int marker = M_PSEUDO;
121+
size_t cur_pos = 2;
122+
123+
while (height == 0 && width == 0 && marker != M_SOS && marker != M_EOI) {
124+
int a = 0, comment_correction = 1 + (marker == M_COM), new_marker;
125+
126+
do {
127+
if (cur_pos == size) {
128+
new_marker = M_EOI;
129+
break;
130+
}
131+
new_marker = image[cur_pos++];
132+
if (marker == M_COM && comment_correction > 0) {
133+
if (new_marker != 0xFF) {
134+
new_marker = 0xFF;
135+
comment_correction--;
136+
} else {
137+
marker = M_PSEUDO;
138+
}
139+
}
140+
a++;
141+
} while (new_marker == 0xff);
142+
143+
if (a < 2 || (marker == M_COM && comment_correction)) {
144+
new_marker = M_EOI;
145+
}
146+
147+
marker = new_marker;
148+
149+
switch (marker) {
150+
case M_SOF0:
151+
case M_SOF1:
152+
case M_SOF2:
153+
case M_SOF3:
154+
case M_SOF5:
155+
case M_SOF6:
156+
case M_SOF7:
157+
case M_SOF9:
158+
case M_SOF10:
159+
case M_SOF11:
160+
case M_SOF13:
161+
case M_SOF14:
162+
case M_SOF15:
163+
if (cur_pos + 8 > size) {
164+
RuntimeAllocator::get().free_script_memory(image, size);
165+
return false;
166+
}
167+
bits = image[cur_pos + 2];
168+
height = (image[cur_pos + 3] << 8) + image[cur_pos + 4];
169+
width = (image[cur_pos + 5] << 8) + image[cur_pos + 6];
170+
channels = image[cur_pos + 7];
171+
cur_pos += 8;
172+
173+
case M_SOS:
174+
case M_EOI:
175+
break;
176+
177+
default: {
178+
size_t length = (image[cur_pos] << 8) + image[cur_pos + 1];
179+
180+
if (length < 2 || cur_pos + length > size) {
181+
RuntimeAllocator::get().free_script_memory(image, size);
182+
return false;
183+
}
184+
cur_pos += length;
185+
break;
186+
}
187+
}
188+
}
189+
RuntimeAllocator::get().free_script_memory(image, size);
190+
} else if (!std::strncmp((const char*)buf.begin(), php_sig_jpc.begin(), sizeof(php_sig_jpc)) && static_cast<int>(read_size) >= 42) {
191+
type = IMAGETYPE_JPEG;
192+
193+
width = (buf[8] << 24) + (buf[9] << 16) + (buf[10] << 8) + buf[11];
194+
height = (buf[12] << 24) + (buf[13] << 16) + (buf[14] << 8) + buf[15];
195+
channels = (buf[40] << 8) + buf[41];
196+
197+
if (channels < 0 || channels > 256 || static_cast<int>(read_size) < 42 + 3 * channels || width <= 0 || height <= 0) {
198+
return false;
199+
}
200+
201+
bits = 0;
202+
for (int i = 0; i < channels; i++) {
203+
int cur_bits = buf[42 + 3 * i];
204+
if (cur_bits > bits) {
205+
bits = cur_bits;
206+
}
207+
}
208+
bits++;
209+
} else {
210+
return false;
211+
}
212+
break;
213+
case 0x00: // jp2
214+
if (read_size >= 54 && !std::strncmp((const char*)buf.begin(), php_sig_jp2.begin(), sizeof(php_sig_jp2))) {
215+
type = IMAGETYPE_JP2;
216+
217+
bool found = false;
218+
219+
int buf_pos = 12;
220+
size_t file_pos = 12;
221+
while (static_cast<int>(read_size) >= 42 + buf_pos + 8) {
222+
const unsigned char* s = buf.begin() + buf_pos;
223+
int box_length = (s[0] << 24) + (s[1] << 16) + (s[2] << 8) + s[3];
224+
if (box_length == 1 || box_length > 1000000000) {
225+
break;
226+
}
227+
if (s[4] == 'j' && s[5] == 'p' && s[6] == '2' && s[7] == 'c') {
228+
s += 8;
229+
230+
width = (s[8] << 24) + (s[9] << 16) + (s[10] << 8) + s[11];
231+
height = (s[12] << 24) + (s[13] << 16) + (s[14] << 8) + s[15];
232+
channels = (s[40] << 8) + s[41];
233+
234+
if (channels < 0 || channels > 256 || static_cast<int>(read_size) < 42 + buf_pos + 8 + 3 * channels || width <= 0 || height <= 0) {
235+
break;
236+
}
237+
238+
bits = 0;
239+
for (int i = 0; i < channels; i++) {
240+
int cur_bits = s[42 + 3 * i];
241+
if (cur_bits > bits) {
242+
bits = cur_bits;
243+
}
244+
}
245+
bits++;
246+
247+
found = true;
248+
break;
249+
}
250+
251+
if (box_length <= 8) {
252+
break;
253+
}
254+
file_pos += box_length;
255+
if (file_pos >= size || static_cast<off_t>(file_pos) != static_cast<ssize_t>(file_pos) || static_cast<ssize_t>(file_pos) < 0) {
256+
break;
257+
}
258+
259+
read_size = min_size;
260+
if (size - file_pos < min_size) {
261+
read_size = size - file_pos;
262+
}
263+
264+
if (read_size < 50) {
265+
break;
266+
}
267+
std::span<unsigned char> buf_read_span(buf.begin(), read_size);
268+
read_res = f->pread(std::as_writable_bytes(buf_read_span), static_cast<off_t>(file_pos));
269+
if (!read_res || *read_res < read_size) {
270+
break;
271+
}
272+
273+
buf_pos = 0;
274+
}
275+
276+
if (!found) {
277+
return false;
278+
}
279+
} else {
280+
return false;
281+
}
282+
break;
283+
case 0x89: // png
284+
if (read_size >= 25 && !std::strncmp((const char*)buf.begin(), php_sig_png.begin(), sizeof(php_sig_png))) {
285+
type = IMAGETYPE_PNG;
286+
width = (buf[16] << 24) + (buf[17] << 16) + (buf[18] << 8) + buf[19];
287+
height = (buf[20] << 24) + (buf[21] << 16) + (buf[22] << 8) + buf[23];
288+
bits = buf[24];
289+
} else {
290+
return false;
291+
}
292+
break;
293+
default:
294+
return false;
295+
}
296+
297+
array<mixed> result(array_size(7, false));
298+
result.push_back(width);
299+
result.push_back(height);
300+
result.push_back(type);
301+
302+
string::size_type len = std::format_to_n(reinterpret_cast<char*>(buf.data()), min_size, "width=\"%d\" height=\"%d\"", width, height).size;
303+
result.push_back(string{(const char*)buf.begin(), len});
304+
if (bits != 0) {
305+
result.set_value(string{"bits", 4}, bits);
306+
}
307+
if (channels != 0) {
308+
result.set_value(string{"channels", 8}, channels);
309+
}
310+
result.set_value(string{"mime", 4}, string{mime_type_string[type].data(), static_cast<string::size_type>(mime_type_string[type].size())});
311+
312+
return result;
313+
}

0 commit comments

Comments
 (0)