mirror of
https://github.com/stenzek/duckstation.git
synced 2026-10-11 22:49:58 +00:00
dep/rcheevos: Bump to e871ef5
This commit is contained in:
@@ -710,10 +710,15 @@ int rc_json_get_string(const char** out, rc_buffer_t* buffer, const rc_json_fiel
|
||||
}
|
||||
|
||||
*out = dst = (char*)rc_buffer_reserve(buffer, len - 1); /* -2 for quotes, +1 for null terminator */
|
||||
if (!dst)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
while (src < field->value_end && *src != '\"') {
|
||||
if (*src == '\\') {
|
||||
++src;
|
||||
if (src >= field->value_end)
|
||||
return 0;
|
||||
|
||||
if (*src == 'n') {
|
||||
/* newline */
|
||||
++src;
|
||||
@@ -731,7 +736,7 @@ int rc_json_get_string(const char** out, rc_buffer_t* buffer, const rc_json_fiel
|
||||
if (*src == 'u') {
|
||||
/* unicode character */
|
||||
uint32_t ucs32_char;
|
||||
if (src + 5 >= field->value_end) /* incomplete unicode character */
|
||||
if ((size_t)(field->value_end - src) < 6) /* incomplete unicode character */
|
||||
return 0;
|
||||
|
||||
ucs32_char = rc_json_decode_hex4(src + 1);
|
||||
@@ -739,7 +744,7 @@ int rc_json_get_string(const char** out, rc_buffer_t* buffer, const rc_json_fiel
|
||||
|
||||
if (ucs32_char >= 0xD800 && ucs32_char < 0xE000) {
|
||||
/* surrogate lead - look for surrogate tail */
|
||||
if (ucs32_char < 0xDC00 && src[0] == '\\' && src[1] == 'u') {
|
||||
if (ucs32_char < 0xDC00 && (size_t)(field->value_end - src) >= 6 && src[0] == '\\' && src[1] == 'u') {
|
||||
const uint32_t surrogate = rc_json_decode_hex4(src + 2);
|
||||
src += 6;
|
||||
|
||||
@@ -770,10 +775,16 @@ int rc_json_get_string(const char** out, rc_buffer_t* buffer, const rc_json_fiel
|
||||
}
|
||||
|
||||
*dst++ = *src++;
|
||||
} while (*src != '\"');
|
||||
}
|
||||
|
||||
if (src >= field->value_end)
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
*out = dst = (char*)rc_buffer_reserve(buffer, len + 1); /* +1 for null terminator */
|
||||
if (!dst)
|
||||
return 0;
|
||||
|
||||
memcpy(dst, src, len);
|
||||
dst += len;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ static int rc_api_process_fetch_game_data_achievements(rc_api_response_t* respon
|
||||
while (rc_json_get_array_entry_object(achievement_fields, sizeof(achievement_fields) / sizeof(achievement_fields[0]), &iterator)) {
|
||||
if (!rc_json_get_required_unum(&achievement->id, response, &achievement_fields[0], "ID"))
|
||||
return RC_MISSING_VALUE;
|
||||
if (!rc_json_get_required_string(&achievement->title, response, &achievement_fields[1], "Title"))
|
||||
if (!rc_json_get_required_string(&achievement->title, response, &achievement_fields[1], "Title") || !achievement->title)
|
||||
return RC_MISSING_VALUE;
|
||||
if (!rc_json_get_required_string(&achievement->description, response, &achievement_fields[2], "Description"))
|
||||
return RC_MISSING_VALUE;
|
||||
@@ -197,16 +197,18 @@ static int rc_api_process_fetch_game_data_achievements(rc_api_response_t* respon
|
||||
achievement->type = RC_ACHIEVEMENT_TYPE_STANDARD;
|
||||
|
||||
/* legacy support : if title contains[m], change type to missable and remove[m] from title */
|
||||
if (memcmp(achievement->title, "[m]", 3) == 0) {
|
||||
/* since we're comparing a suffix, calculate the length in case it contains null bytes */
|
||||
len = strlen(achievement->title);
|
||||
if (len >= 3 && memcmp(achievement->title, "[m]", 3) == 0) {
|
||||
len = 3;
|
||||
while (achievement->title[len] == ' ')
|
||||
++len;
|
||||
achievement->title += len;
|
||||
achievement->type = RC_ACHIEVEMENT_TYPE_MISSABLE;
|
||||
}
|
||||
else if (achievement_fields[1].value_end && memcmp(achievement_fields[1].value_end - 4, "[m]", 3) == 0) {
|
||||
len = strlen(achievement->title) - 3;
|
||||
while (achievement->title[len - 1] == ' ')
|
||||
else if (len >= 3 && memcmp(achievement->title + len - 3, "[m]", 3) == 0) {
|
||||
len -= 3;
|
||||
while (len > 0 && achievement->title[len - 1] == ' ')
|
||||
--len;
|
||||
((char*)achievement->title)[len] = '\0';
|
||||
achievement->type = RC_ACHIEVEMENT_TYPE_MISSABLE;
|
||||
|
||||
@@ -56,6 +56,11 @@ uint8_t* rc_buffer_reserve(rc_buffer_t* buffer, size_t amount)
|
||||
{
|
||||
rc_buffer_chunk_t* chunk = &buffer->chunk;
|
||||
size_t remaining;
|
||||
|
||||
/* we should never need 1GB of space for anything, and avoids any underflow below */
|
||||
if (amount >= 0x40000000)
|
||||
return NULL;
|
||||
|
||||
while (chunk)
|
||||
{
|
||||
remaining = chunk->end - chunk->write;
|
||||
@@ -112,6 +117,9 @@ void rc_buffer_consume(rc_buffer_t* buffer, const uint8_t* start, uint8_t* end)
|
||||
void* rc_buffer_alloc(rc_buffer_t* buffer, size_t amount)
|
||||
{
|
||||
uint8_t* ptr = rc_buffer_reserve(buffer, amount);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
rc_buffer_consume(buffer, ptr, ptr + amount);
|
||||
return (void*)ptr;
|
||||
}
|
||||
@@ -119,6 +127,9 @@ void* rc_buffer_alloc(rc_buffer_t* buffer, size_t amount)
|
||||
char* rc_buffer_strncpy(rc_buffer_t* buffer, const char* src, size_t len)
|
||||
{
|
||||
uint8_t* dst = rc_buffer_reserve(buffer, len + 1);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
memcpy(dst, src, len);
|
||||
dst[len] = '\0';
|
||||
rc_buffer_consume(buffer, dst, dst + len + 1);
|
||||
|
||||
@@ -363,7 +363,8 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) {
|
||||
|
||||
classification = combining_classification;
|
||||
}
|
||||
else {
|
||||
else if (classification != RC_CONDITION_CLASSIFICATION_INDIRECT) {
|
||||
/* if it's not COMBINING or INDIRECT, reset so it will get recalculated for the next clause */
|
||||
combining_classification = RC_CONDITION_CLASSIFICATION_COMBINING;
|
||||
}
|
||||
|
||||
|
||||
@@ -319,13 +319,30 @@ int rc_operands_are_equal(const rc_operand_t* left, const rc_operand_t* right) {
|
||||
case RC_OPERAND_FP:
|
||||
return (left->value.dbl == right->value.dbl);
|
||||
case RC_OPERAND_RECALL:
|
||||
return (left->value.memref == right->value.memref);
|
||||
if (left->memref_access_type != right->memref_access_type)
|
||||
return 0;
|
||||
switch (left->memref_access_type) {
|
||||
case RC_OPERAND_CONST:
|
||||
return (left->value.num == right->value.num);
|
||||
case RC_OPERAND_FP:
|
||||
return (left->value.dbl == right->value.dbl);
|
||||
default:
|
||||
if (!left->value.memref || !right->value.memref) /* could not find remember */
|
||||
return 0;
|
||||
break; /* fallthrough to memref comparison */
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* comparing two memrefs - look for exact matches on type and size */
|
||||
if (left->size != right->size || left->value.memref->value.memref_type != right->value.memref->value.memref_type)
|
||||
if (left->size != right->size)
|
||||
return 0;
|
||||
|
||||
if (left->value.memref == right->value.memref) /* quick match if pointing to same memref */
|
||||
return 1;
|
||||
|
||||
if (left->value.memref->value.memref_type != right->value.memref->value.memref_type)
|
||||
return 0;
|
||||
|
||||
switch (left->value.memref->value.memref_type) {
|
||||
@@ -336,8 +353,7 @@ int rc_operands_are_equal(const rc_operand_t* left, const rc_operand_t* right) {
|
||||
return (left_memref->modifier_type == right_memref->modifier_type &&
|
||||
left_memref->depth == right_memref->depth &&
|
||||
rc_operands_are_equal(&left_memref->modifier, &right_memref->modifier) &&
|
||||
rc_operands_are_equal(&left_memref->parent, &right_memref->parent) &&
|
||||
1 == 1
|
||||
rc_operands_are_equal(&left_memref->parent, &right_memref->parent)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1210,8 +1210,10 @@ static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, co
|
||||
|
||||
/* combining field didn't match, or there's more unmatched combining fields. ignore this condition */
|
||||
if (!chain_matches || rc_validate_is_combining_condition(compare_condition)) {
|
||||
while (compare_condition->next && rc_validate_is_combining_condition(compare_condition))
|
||||
while (compare_condition->next && rc_validate_is_combining_condition(compare_condition)) {
|
||||
++state->cond_index;
|
||||
compare_condition = compare_condition->next;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -802,7 +802,7 @@ static int rc_evaluate_richpresence_display(rc_richpresence_display_part_t* part
|
||||
value.value.u32 = '?';
|
||||
|
||||
tmp[chars++] = (char)value.value.u32;
|
||||
if (chars == sizeof(tmp) || !part->next || part->next->display_type != RC_FORMAT_ASCIICHAR)
|
||||
if (chars == sizeof(tmp) - 1 || !part->next || part->next->display_type != RC_FORMAT_ASCIICHAR)
|
||||
break;
|
||||
|
||||
part = part->next;
|
||||
|
||||
@@ -159,8 +159,14 @@ static void rc_parse_legacy_value(rc_value_t* self, const char** memaddr, rc_par
|
||||
/* if it looks like a floating point number, add the 'f' prefix */
|
||||
while (isdigit((unsigned char)*buffer_ptr))
|
||||
++buffer_ptr;
|
||||
if (*buffer_ptr == '.')
|
||||
if (*buffer_ptr == '.') {
|
||||
if (ptr == &buffer[sizeof(buffer)]) {
|
||||
parse->offset = RC_INVALID_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
*ptr++ = 'f';
|
||||
}
|
||||
continue;
|
||||
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user