Skip to content

Commit 1625d35

Browse files
Merge pull request #71 from NathanNeurotic/codex/fix-memcpy-usage-to-validate-buffer-sizes
Harden sceCdRM buffer handling and simplify PS1 helpers
2 parents c9bb0da + 736c9df commit 1625d35

4 files changed

Lines changed: 62 additions & 35 deletions

File tree

include/libcdvd_add.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ int custom_sceCdReadRegionParams(u8 *data, u32 *stat);
1313
*/
1414
int custom_sceCdReadPS1BootParam(char *param, u32 *stat);
1515

16-
// Obtain model number from EEPROM via the mechacon SCMD 0x17
16+
// Obtain model number from EEPROM via the mechacon SCMD 0x17.
17+
// The caller must provide a buffer of at least 16 bytes (two 8-byte chunks).
1718
int sceCdRM(char *ModelName, u32 *stat);
1819

1920
// Provides an equivalent of the sceCdBootCertify function from the newer CDVDMAN modules. The old CDVDFSV and CDVDMAN modules don't support this S-command.

src/libcdvd_add.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "debugprintf.h"
88
#include "libcdvd_add.h"
9+
#include "util_safe.h"
910

1011
static unsigned char MECHACON_CMD_S36_supported = 0, MECHACON_CMD_S27_supported = 0, MECHACON_CMD_S24_supported = 0;
1112

@@ -70,20 +71,32 @@ int sceCdRM(char *ModelName, u32 *stat)
7071
unsigned char rdata[9];
7172
unsigned char sdata;
7273
int result1, result2;
74+
const size_t modelNameSize = 16; // Two 8-byte chunks
75+
76+
if (ModelName == NULL || stat == NULL) {
77+
return 0;
78+
}
79+
80+
memset(rdata, 0, sizeof(rdata));
81+
memset(ModelName, 0, modelNameSize);
7382

7483
sdata = 0;
7584
result1 = sceCdApplySCmd(0x17, &sdata, 1, rdata);
7685
// result1 = sceCdApplySCmd(0x17, &sdata, 1, rdata, 9);
7786

7887
*stat = rdata[0];
79-
memcpy(ModelName, &rdata[1], 8);
88+
if (result1 != 0 && util_memcpy_s(ModelName, modelNameSize, &rdata[1], 8) != 0) {
89+
result1 = 0;
90+
}
8091

8192
sdata = 8;
8293
result2 = sceCdApplySCmd(0x17, &sdata, 1, rdata);
8394
// result2 = sceCdApplySCmd(0x17, &sdata, 1, rdata, 9);
8495

8596
*stat |= rdata[0];
86-
memcpy(&ModelName[8], &rdata[1], 8);
97+
if (result2 != 0 && util_memcpy_s(&ModelName[8], modelNameSize - 8, &rdata[1], 8) != 0) {
98+
result2 = 0;
99+
}
87100

88101
return ((result1 != 0 && result2 != 0) ? 1 : 0);
89102
}

src/ps1.c

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,31 @@ static char ps1drv_ver[64] = "";
3232

3333
#define CNF_PATH_LEN_MAX 64
3434

35+
static int HandleChineseBootParam(void)
36+
{
37+
u32 stat;
38+
39+
if (OSDGetConsoleRegion() != CONSOLE_REGION_CHINA) {
40+
return -1;
41+
}
42+
43+
custom_sceCdReadPS1BootParam(ps1drv_boot, &stat);
44+
45+
if (stat & 0x180) { // Command unsupported or failed for some reason.
46+
return 0;
47+
}
48+
49+
if (ps1drv_boot[4] == '-')
50+
ps1drv_boot[4] = '_';
51+
52+
ps1drv_boot[11] = '\0';
53+
ps1drv_boot[10] = ps1drv_boot[9];
54+
ps1drv_boot[9] = ps1drv_boot[8];
55+
ps1drv_boot[8] = '.';
56+
57+
return 1;
58+
}
59+
3560
int PS1DRVInit(void)
3661
{
3762
const char *pChar;
@@ -142,35 +167,15 @@ static void CNFGetKey(char *cnf, char *line, const char *key)
142167

143168
static int ParseBootCNF(void)
144169
{
145-
u32 stat;
146170
int fd;
171+
int chinese_result;
147172

148173
util_strlcpy(ps1drv_ver, "???", sizeof(ps1drv_ver));
149174
util_strlcpy(ps1drv_boot, "???", sizeof(ps1drv_boot));
150175

151-
if (OSDGetConsoleRegion() == CONSOLE_REGION_CHINA) { // China
152-
/* I do not know why Sony did this for the Chinese console (SCPH-50009).
153-
Perhaps it as an act to strengthen their DRM for that release,
154-
since PlayStation 2 game booting is also slightly different.
155-
156-
It is normally possible to actually parse SYSTEM.CNF and get the boot filename from BOOT.
157-
Lots of homebrew software do that, and so does Sony (for all other regions).
158-
But I do not know for sure whether that can be done for Chinese PlayStation discs. */
159-
custom_sceCdReadPS1BootParam(ps1drv_boot, &stat);
160-
161-
if (stat & 0x180) { // Command unsupported or failed for some reason.
162-
return 0;
163-
}
164-
165-
if (ps1drv_boot[4] == '-')
166-
ps1drv_boot[4] = '_';
167-
168-
ps1drv_boot[11] = '\0';
169-
ps1drv_boot[10] = ps1drv_boot[9];
170-
ps1drv_boot[9] = ps1drv_boot[8];
171-
ps1drv_boot[8] = '.';
172-
173-
return 1;
176+
chinese_result = HandleChineseBootParam();
177+
if (chinese_result >= 0) {
178+
return chinese_result;
174179
}
175180

176181
if ((fd = open("cdrom0:\\SYSTEM.CNF;1", O_RDWR)) >= 0) {

src/util_safe.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,24 @@ size_t util_strlcpy(char *dst, const char *src, size_t dst_size)
3232
{
3333
const size_t src_len = util_bounded_strnlen(src, SIZE_MAX);
3434

35-
if (dst_size > 0 && dst != NULL) {
36-
const size_t copy_len = (src_len >= dst_size) ? dst_size - 1 : src_len;
37-
38-
if (src != NULL && copy_len > 0) {
39-
if (util_memcpy_s(dst, dst_size, src, copy_len) != 0)
40-
return src_len;
41-
}
42-
dst[copy_len] = '\0';
35+
if (dst == NULL || dst_size == 0) {
36+
return src_len;
4337
}
4438

39+
if (src == NULL) {
40+
dst[0] = '\0';
41+
return src_len;
42+
}
43+
44+
const size_t copy_len = (src_len >= dst_size) ? dst_size - 1 : src_len;
45+
46+
if (copy_len > 0 && util_memcpy_s(dst, dst_size, src, copy_len) != 0) {
47+
dst[0] = '\0';
48+
return src_len;
49+
}
50+
51+
dst[copy_len] = '\0';
52+
4553
return src_len;
4654
}
4755

0 commit comments

Comments
 (0)