Merge pull request #783 from ennorehling/develop

bugfixes, string escaping
This commit is contained in:
Enno Rehling 2018-05-26 21:25:08 +02:00 committed by GitHub
commit ef7ee57893
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 202 additions and 33 deletions

View File

@ -308,7 +308,7 @@ msgstr "\"$unit($mage) legt einen Schleier um die Ausrüstung von $unit.dative($
msgid "error5"
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Das Gebäude gehört uns nicht.\""
msgid "tactics_lost"
msgid "para_tactics_lost"
msgstr "\"$unit($unit) konnte dem Gegner eine Falle stellen.\""
msgid "error_lowstealth"
@ -1052,7 +1052,7 @@ msgstr "\"Diese Region wurde von den Göttern verflucht. Stinkende Nebel ziehen
msgid "recruit_archetype"
msgstr "\"$unit($unit) rekrutiert $int($amount) $localize($archetype).\""
msgid "tactics_won"
msgid "para_tactics_won"
msgstr "\"$unit($unit) überrascht den Gegner.\""
msgid "raindance_effect"

View File

@ -308,7 +308,7 @@ msgstr "\"$unit($mage) shrouds the equipment of $unit($target) in shadows.\""
msgid "error5"
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The building is not ours.\""
msgid "tactics_lost"
msgid "para_tactics_lost"
msgstr "\"$unit($unit) lured the enemy into an ambush.\""
msgid "error_lowstealth"
@ -1052,7 +1052,7 @@ msgstr "\"This region was cursed by the gods. Stinking vapors billow over the de
msgid "recruit_archetype"
msgstr "\"$unit($unit) recruits $int($amount) $localize($archetype).\""
msgid "tactics_won"
msgid "para_tactics_won"
msgstr "\"$unit($unit) surprises the enemies.\""
msgid "raindance_effect"

View File

@ -2859,7 +2859,7 @@ msgid "Blut"
msgstr "Blut"
msgid "nr_guarding_prefix"
msgstr "Die Region wird von"
msgstr "Die Region wird von "
msgctxt "race"
msgid "giantturtle"
@ -4083,7 +4083,7 @@ msgid "section_newspells"
msgstr "Neue Zauber"
msgid "nr_borderlist_prefix"
msgstr "Im"
msgstr "Im "
msgctxt "race"
msgid "greenscarab_d"
@ -4156,7 +4156,7 @@ msgid "seed"
msgstr "Same"
msgid "nr_nb_next"
msgstr ", im"
msgstr ", im "
msgctxt "spellinfo"
msgid "undeadhero"
@ -4823,7 +4823,7 @@ msgid "juju_d"
msgstr "Juju-Zombies"
msgid "nr_guarding_postfix"
msgstr "bewacht."
msgstr " bewacht."
msgctxt "border"
msgid "fogwall"
@ -5852,7 +5852,7 @@ msgid "clone_of"
msgstr "Klon von %s"
msgid "travelthru_header"
msgstr "Die Region wurde durchquert von"
msgstr "Die Region wurde durchquert von "
msgctxt "race"
msgid "template_x"

View File

@ -2960,10 +2960,10 @@ static void print_stats(battle * b)
unit *u = tf->unit;
message *m = NULL;
if (!is_attacker(tf)) {
m = msg_message("tactics_lost", "unit", u);
m = msg_message("para_tactics_lost", "unit", u);
}
else {
m = msg_message("tactics_won", "unit", u);
m = msg_message("para_tactics_won", "unit", u);
}
message_all(b, m);
msg_release(m);

View File

@ -517,7 +517,7 @@ static void report_crtypes(FILE * F, const struct locale *lang)
assert(hash > 0);
fprintf(F, "MESSAGETYPE %d\n", hash);
fputc('\"', F);
fputs(str_escape(nrt_string(kmt->mtype, lang), buffer, sizeof(buffer)), F);
fputs(crescape(nrt_string(kmt->mtype, lang), buffer, sizeof(buffer)), F);
fputs("\";text\n", F);
fprintf(F, "\"%s\";section\n", kmt->mtype->section);
}

View File

@ -5,6 +5,8 @@
#include "alchemy.h"
#include "modules/score.h"
#include "kernel/build.h"
#include "kernel/building.h"
#include "kernel/item.h"
@ -229,6 +231,9 @@ static void handle_item(parseinfo *pi, const XML_Char *el, const XML_Char **attr
handle_bad_input(pi, el, attr[i]);
}
}
if (itype->score == 0) {
itype->score = default_score(itype);
}
itype->flags = flags;
}

View File

@ -110,6 +110,15 @@ char* get_command(const order *ord, const struct locale *lang, char *sbuffer, si
return sbuffer;
}
const char *crescape(const char *str, char *buffer, size_t size) {
const char *replace = "\"\\";
const char * pos = strpbrk(str, replace);
if (!pos) {
return str;
}
return str_escape_ex(str, buffer, size, replace);
}
int stream_order(struct stream *out, const struct order *ord, const struct locale *lang, bool escape)
{
const char *text;
@ -151,7 +160,7 @@ int stream_order(struct stream *out, const struct order *ord, const struct local
char obuf[1024];
swrite(" ", 1, 1, out);
if (escape) {
text = str_escape(text, obuf, sizeof(obuf));
text = crescape(text, obuf, sizeof(obuf));
}
swrite(text, 1, strlen(text), out);
}

View File

@ -67,6 +67,7 @@ extern "C" {
bool is_exclusive(const order * ord);
bool is_repeated(keyword_t kwd);
bool is_long(keyword_t kwd);
const char *crescape(const char *str, char *buffer, size_t size);
char *write_order(const order * ord, const struct locale *lang,
char *buffer, size_t size);

View File

@ -14,6 +14,7 @@
#include <tests.h>
#include <CuTest.h>
#include <stdlib.h>
#include <string.h>
static void test_create_order(CuTest *tc) {
char cmd[32];
@ -484,10 +485,60 @@ static void test_study_order_unknown_quoted(CuTest *tc) {
test_teardown();
}
static void test_create_order_long(CuTest *tc) {
char buffer[2048];
order *ord;
struct locale *lang;
stream out;
const char * longstr = "// BESCHREIBEN EINHEIT \"In weiÃ&#131; &#131; &#131; &#131; &#131; &#131; &#131; &#"
"131;&#131;&#131;&#131;&#131;&#131;&#131;?e GewÃ&#131;&#131;&#131;&#131;&#13"
"1;&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#131;Ã&#131;&#131;&#131;"
"&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#131;Ã&#131;&#131;&#131;&#"
"131;&#131;&#131;&#131;&#131;&#131;&#131;&#130;Ã&#131;&#131;&#131;&#131;&#13"
"1;&#131;&#131;&#131;&#131;&#130;Ã&#131;&#131;&#131;&#131;&#131;&#131;&#131;"
"&#131;&#130;Ã&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#130;Ã&#131;&#131;&"
"#131;&#131;&#131;&#131;&#130;Ã&#131;&#131;&#131;&#131;&#131;&#130;Ã&#131;&#"
"131;&#131;&#131;&#130;Ã&#131;&#131;&#131;&#130;Ã&#131;&#131;&#130;Ã&#131;&#"
"130;Ã&#130;¢&#130;Ã&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#131;&"
"#131;&#131;&#130;Ã&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#1"
"31;&#130;Ã&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#130;Ã&#13"
"1;&#131;&#131;&#131;&#131;&#131;&#131;&#131;&#130;Ã&#131;&#131;&#131;&#131;"
"&#131;&#131;&#131;&#130[...]hB&#65533;&#65533;2&#65533;xa&#65533;Hv$P&#65533;xa&#65533;&#65533;A&#65533;&#65533;&#65533;A&#65533;&#65533;";
test_setup();
lang = test_create_locale();
ord = parse_order(longstr, lang);
CuAssertIntEquals(tc, 0, ord->command);
mstream_init(&out);
stream_order(&out, ord, lang, true);
out.api->rewind(out.handle);
out.api->readln(out.handle, buffer, sizeof(buffer));
mstream_done(&out);
free_order(ord);
test_teardown();
}
static void test_crescape(CuTest *tc) {
char buffer[16];
const char *input = "12345678901234567890";
CuAssertStrEquals(tc, "1234", crescape("1234", buffer, 16));
CuAssertPtrEquals(tc, (void *)input, (void *)crescape(input, buffer, 16));
CuAssertStrEquals(tc, "\\\"1234\\\"", crescape("\"1234\"", buffer, 16));
CuAssertStrEquals(tc, "\\\"1234\\\"", buffer);
CuAssertStrEquals(tc, "\\\"1234", crescape("\"1234\"", buffer, 8));
/* unlike in C strings, only " and \ are escaped: */
CuAssertStrEquals(tc, "\\\"\\\\\n\r\'", crescape("\"\\\n\r\'", buffer, 16));
}
CuSuite *get_order_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_crescape);
SUITE_ADD_TEST(suite, test_create_order);
SUITE_ADD_TEST(suite, test_create_order_long);
SUITE_ADD_TEST(suite, test_study_orders);
SUITE_ADD_TEST(suite, test_study_order);
SUITE_ADD_TEST(suite, test_study_order_unknown);

View File

@ -46,7 +46,7 @@
static int read_permissions(variant *var, void *owner, struct gamedata *data)
{
attrib *a;
attrib *a = NULL;
UNUSED_ARG(var);
read_attribs(data, &a, owner);
a_remove(&a, a);

View File

@ -172,8 +172,8 @@ static order *monster_attack(unit * u, const unit * target)
if (monster_is_waiting(u))
return NULL;
if (u->region->land) {
assert(u->region->flags & RF_GUARDED);
if (u->region->land && (u->region->flags & RF_GUARDED) == 0) {
return NULL;
}
return create_order(K_ATTACK, u->faction->locale, "%i", target->no);
}

View File

@ -20,9 +20,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <platform.h>
#endif
#include "strings.h"
#include "assert.h"
/* libc includes */
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
@ -155,27 +155,28 @@ int str_hash(const char *s)
return key & 0x7FFFFFFF;
}
const char *str_escape(const char *str, char *buffer, size_t len)
const char *str_escape_wrong(const char *str, char *buffer, size_t len)
{
const char *handle_start = strchr(str, '\"');
if (!handle_start) handle_start = strchr(str, '\\');
assert(buffer);
if (handle_start) {
const char *p;
char *o;
const char *p = str;
char *o = buffer;
size_t skip = handle_start - str;
if (skip > len) {
skip = len;
}
memcpy(buffer, str, skip);
o = buffer + skip;
p = str + skip;
len -= skip;
if (skip > 0) {
memcpy(buffer, str, skip);
o += skip;
p += skip;
len -= skip;
}
do {
if (*p == '\"' || *p == '\\') {
if (len < 2) {
*o = '\0';
break;
}
(*o++) = '\\';
@ -183,13 +184,15 @@ const char *str_escape(const char *str, char *buffer, size_t len)
}
else {
if (len < 1) {
*o = '\0';
break;
}
--len;
}
(*o++) = (*p);
} while (*p++);
if (len > 0) {
(*o++) = (*p);
}
} while (len > 0 && *p++);
*o = '\0';
return buffer;
}
return str;
@ -306,3 +309,88 @@ char *str_unescape(char *str) {
}
return str;
}
const char *str_escape_ex(const char *str, char *buffer, size_t size, const char *chars)
{
const char *read = str;
char *write = buffer;
if (size < 1) return NULL;
while (size > 1 && *read) {
const char *pos = strpbrk(read, chars);
size_t len = size;
if (pos) {
len = pos - read;
}
if (len < size) {
unsigned char ch = *(const unsigned char *)pos;
if (len > 0) {
memmove(write, read, len);
write += len;
read += len;
size -= len;
}
switch (ch) {
case '\t':
if (size > 2) {
*write++ = '\\';
*write++ = 't';
size -= 2;
}
else size = 1;
break;
case '\n':
if (size > 2) {
*write++ = '\\';
*write++ = 'n';
size -= 2;
}
else size = 1;
break;
case '\r':
if (size > 2) {
*write++ = '\\';
*write++ = 'r';
size -= 2;
}
else size = 1;
break;
case '\"':
case '\'':
case '\\':
if (size > 2) {
*write++ = '\\';
*write++ = ch;
size -= 2;
}
break;
default:
if (size > 5) {
int n = sprintf(write, "\\%03o", ch);
if (n > 0) {
assert(n == 5);
write += n;
size -= n;
}
else size = 1;
}
else size = 1;
}
++read;
} else {
/* end of buffer space */
len = size - 1;
if (len > 0) {
memmove(write, read, len);
write += len;
size -= len;
break;
}
}
}
*write = '\0';
return buffer;
}
const char *str_escape(const char *str, char *buffer, size_t size) {
return str_escape_ex(str, buffer, size, "\n\t\r\'\"\\");
}

View File

@ -32,7 +32,8 @@ extern "C" {
size_t str_strlcat(char *dst, const char *src, size_t len);
char *str_strdup(const char *s);
const char *str_escape(const char *str, char *buffer, size_t len);
const char *str_escape(const char *str, char *buffer, size_t size);
const char *str_escape_ex(const char *str, char *buffer, size_t size, const char *chars);
char *str_unescape(char *str);
unsigned int jenkins_hash(unsigned int a);

View File

@ -24,10 +24,24 @@ static void test_str_unescape(CuTest * tc)
static void test_str_escape(CuTest * tc)
{
char scratch[64];
CuAssertStrEquals(tc, "12345678901234567890", str_escape("12345678901234567890", scratch, 16));
CuAssertStrEquals(tc, "123456789\\\"12345", str_escape("123456789\"1234567890", scratch, 16));
CuAssertStrEquals(tc, "1234567890123456", str_escape("1234567890123456\"890", scratch, 16));
char scratch[16];
CuAssertPtrEquals(tc, NULL, (void *)str_escape("1234", scratch, 0));
CuAssertStrEquals(tc, "", str_escape("1234", scratch, 1));
CuAssertStrEquals(tc, "1", str_escape("1234", scratch, 2));
CuAssertStrEquals(tc, "\\n", str_escape("\n234", scratch, 3));
CuAssertStrEquals(tc, "\\n\\r\\t\\\\\\\"\\\'", str_escape("\n\r\t\\\"\'", scratch, 16));
CuAssertStrEquals(tc, "12345678", str_escape("12345678", scratch, 16));
CuAssertStrEquals(tc, "123456789012345", str_escape("123456789012345", scratch, 16));
CuAssertStrEquals(tc, "12345678901234", str_escape("12345678901234\n", scratch, 15));
CuAssertStrEquals(tc, "123456789012345", str_escape("12345678901234567890", scratch, 16));
CuAssertStrEquals(tc, "\\\\\\\"234", str_escape("\\\"234567890", scratch, 8));
CuAssertStrEquals(tc, "\\\"\\\\234", str_escape("\"\\234567890", scratch, 8));
CuAssertStrEquals(tc, "123456789012345", str_escape("12345678901234567890", scratch, 16));
CuAssertStrEquals(tc, "123456789\\\"1234", str_escape("123456789\"1234567890", scratch, 16));
CuAssertStrEquals(tc, "123456789012345", str_escape("1234567890123456\"890", scratch, 16));
CuAssertStrEquals(tc, "hello world", str_escape("hello world", scratch, sizeof(scratch)));
CuAssertStrEquals(tc, "hello \\\"world\\\"", str_escape("hello \"world\"", scratch, sizeof(scratch)));
CuAssertStrEquals(tc, "\\\"\\\\", str_escape("\"\\", scratch, sizeof(scratch)));