From d886b43107d57235ca0d7d464ab2a9f8660b855b Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 21 Jun 2022 08:57:58 -0700 Subject: [PATCH] fix [again] exploiting artifact name rejection Reported by entrez: attempting to name certain undiscovered items after an artifact could be used to tell whether the item being named was the same type as the artifact, so trying to name a gray stone the Heart of Ahriman would let you tell whether it was a luckstone. That was fixed years ago to reject for any undiscovered gray stone rather than only for luckstone; you'll get "your hand slips" and the name would be smudged. But that fix allowed a loophole and could still be exploited if the player used lowercase for the name: it would get changed to mixed capitalization if the object was the artifact's type or stay lowercase if it only matched by description. This changes to the capitalized name even when the type isn't an exact match, so attempting to name either a luckstone or a touchstone "the heart of ahriman" will name it "The Aeart of Xhriman" with at least one smudged letter to avoid the actual artifact name. Unrelated change: when attempting to apply a new name to an existing artifact, it now says " resists" rather than "The artifact seems to resist" because there's no "seeming" about it. --- doc/fixes3-7-0.txt | 3 +++ src/do_name.c | 29 +++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index d7f742c7bf..81f06cce13 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -925,6 +925,9 @@ be less specific when cause of death is "handling a " that adjust the row placement of copyright and early startup messages so that aren't partially overwritten by prompts that follow ball and chain could be accessed after having been freed if bones were saved +early post-3.4.3 tried to fix the "naming artifacts trick" which could be used + to distinguish the type of some undiscovered items, but using a name + that only matched an artifact after capitalization was exploitable Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/do_name.c b/src/do_name.c index c153e8c0d0..1b007eb3f1 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -1252,7 +1252,7 @@ do_oname(struct obj *obj) { char *bufp, buf[BUFSZ], bufcpy[BUFSZ], qbuf[QBUFSZ]; const char *aname; - short objtyp; + short objtyp = STRANGE_OBJECT; /* Do this now because there's no point in even asking for a name */ if (obj->otyp == SPE_NOVEL) { @@ -1285,15 +1285,21 @@ do_oname(struct obj *obj) * Orcrist, clearly being literate (no pun intended...). */ + if (obj->oartifact) { + /* this used to give "The artifact seems to resist the attempt." + but resisting is definite, no "seems to" about it */ + pline("%s resists the attempt.", + /* any artifact should always pass the has_oname() test + but be careful just in case */ + has_oname(obj) ? ONAME(obj) : "The artifact"); + return; + } + /* relax restrictions over proper capitalization for artifacts */ if ((aname = artifact_name(buf, &objtyp, TRUE)) != 0 - && objtyp == obj->otyp) + && (restrict_name(obj, aname) || exist_artifact(obj->otyp, aname))) { + /* substitute canonical spelling before slippage */ Strcpy(buf, aname); - - if (obj->oartifact) { - pline_The("artifact seems to resist the attempt."); - return; - } else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) { /* this used to change one letter, substituting a value of 'a' through 'y' (due to an off by one error, 'z' would never be selected) and then force that to @@ -1307,7 +1313,7 @@ do_oname(struct obj *obj) because buf[] matches a valid artifact name) */ Strcpy(bufcpy, buf); /* for "the Foo of Bar", only scuff "Foo of Bar" part */ - bufp = !strncmpi(bufcpy, "the ", 4) ? (buf + 4) : buf; + bufp = !strncmpi(buf, "the ", 4) ? (buf + 4) : buf; do { wipeout_text(bufp, rn2_on_display_rng(2), (unsigned) 0); } while (!strcmp(buf, bufcpy)); @@ -1317,8 +1323,15 @@ do_oname(struct obj *obj) /* violate illiteracy conduct since hero attempted to write a valid artifact name */ u.uconduct.literate++; + } else if (obj->otyp == objtyp) { + /* artifact_name() found a match and restrict_name() didn't reject + it; since 'obj' is the right type, naming will change it into an + artifact so use canonical capitalization (Sting or Orcrist) */ + Strcpy(buf, aname); } + obj = oname(obj, buf, ONAME_VIA_NAMING | ONAME_KNOW_ARTI); + nhUse(obj); } struct obj *