• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

C++ IsSupress(type) crash

JayMeazy

Member
Joined
Sep 7, 2020
Messages
92
Solutions
2
Reaction score
24
Hello, I tried to add login Protection for 10 seconds via condition, just a generic condition, the same as CONDITION_MUTED, but it's crashing the server, even if no one logs on and receives the condition which is what struck me as strange, which is why I initially didn't think this was the problem, but after learning a small amount about how to use a debugger, I can see that isSuprress, which returns
Code:
return hasBitSet(static_cast<uint32_t>(type), getConditionSuppressions());
is crashing the server, because CONDITION_LOGINPROTECTION says in debugger the value is CONDITION_LOGINPROTECTION (-2147483648)

does being the 32nd value in the ConditionType_t table have something to do with the bitset crashing?
CONDITION_LOGINPROTECTION = 1 << 31,

this is the only thing I can think of because I've added already added a few custom conditions and they never caused this problem. The worst part of it is on Ubuntu it didn't crash right away for whatever reason, only sometimes I guess it would crash it, I'm not 100% sure, I'll test this further so that I can be sure that this was the crash I was experiencing, but on Windows it crashes often, without any players, not long after it goes online.

If so I guess I'll have to start setting up another condition similar to CONDITION_ATTRIBUTES.
 
Very little information about it so they can help you quickly
Engine version?
it may be TFS 1.x +
and the code it shows in the publication has nothing to do with it, its problem is related to the new custom conditions that it has included, it is more than obvious, so it is better because it does not provide what it has included to its sources and so we can see the problems you have included with it, perhaps it is due to an overflow of numerical capacity, when working with very large numbers in the case they are used for example:

C++:
ITEM_ATTRIBUTE_CUSTOM = 1U << 31
instead of
C++:
ITEM_ATTRIBUTE_CUSTOM = 1 << 31

in your case:
C++:
CONDITION_LOGINPROTECTION = 1 << 31,

you should probably also modify this:
C++:
enum ConditionType_t {
for this:
C++:
enum ConditionType_t : uint32_t {
 
thank you, weird that it would only throw exceptions sometimes, seemed like right after a server save, which struck me as people duping.
 
I did that and apparently that's not enough to hold the crash back, it does make it less frequent but once I summon a few monsters it throws it, memory access violation at 0x00000000000000, which i think has to do with the other functions being used, here's isSuppress:
Code:
bool Creature::isSuppress(ConditionType_t type) const
{
    return hasBitSet(static_cast<uint32_t>(type), getConditionSuppressions());
}
And then here's hasBitSet:
Code:
constexpr bool hasBitSet(uint32_t flag, uint32_t flags) {
    return (flags & flag) != 0;
}
and here's getConditionSuppressions(), there's 1 in creature.h and 1 in player.h:
Code:
        virtual uint32_t getConditionSuppressions() const {
            return 0;
        }
I'm going to make a second hasBitSet function that accepts uint64_t parameters, and see what I can come up, and convert the rest to uint64_t and see what happens, I'll update this
 
Last edited:
Your crash have nothing to do with bitwise operation, bitwise instructions can't throw any exception. If your code have overflow due to insufficient datatype then compiler will inform you about this and even if it will not inform you it still wouldn't be reason why it is crashing.
You have ub that's called "nullptr dereference"(memory access violation at 0x00000000000000).
 
Your crash have nothing to do with bitwise operation, bitwise instructions can't throw any exception. If your code have overflow due to insufficient datatype then compiler will inform you about this and even if it will not inform you it still wouldn't be reason why it is crashing.
You have ub that's called "nullptr dereference"(memory access violation at 0x00000000000000).
Whenever I use Visual Studio debugger, and attach to the exe while it's running, with symbols loaded, it points me to this line:
Code:
bool Creature::hasCondition(ConditionType_t type, uint32_t subId/* = 0*/) const
{
    if (isSuppress(type)) { <---
        return false;
    }
are you saying that i'm probably passing a nullptr dereference for creature, wherever I call hasCondition? I'll check.
is there a way for the debugger to point to which one would be doing it? or if it should then does that mean it's in lua?
 
Last edited:
Whenever I use Visual Studio debugger, and attach to the exe while it's running, with symbols loaded, it points me to this line:
Code:
bool Creature::hasCondition(ConditionType_t type, uint32_t subId/* = 0*/) const
{
    if (isSuppress(type)) { <---
        return false;
    }
are you saying that i'm probably passing a nullptr dereference for creature, wherever I call hasCondition? I'll check.
is there a way for the debugger to point to which one would be doing it? or if it should then does that mean it's in lua?
The debugger at the bottom right shows the call stack before blocking, maybe I can trace the problem a bit further back
 
The debugger at the bottom right shows the call stack before blocking, maybe I can trace the problem a bit further back
oh lol, I didn't even have to debug, it says in the warnings about the NULL dereference, and like 5 other NULL dereferences, thanks to you guys I found those, I took out the custom part and made it in lua, now I can spam summon monsters that attack each other and it doesn't crash so that's cool, but I'm still not really sure how it got a Null dereference, I have a few others there, is it because I'm pointing to a creature that could've already returned false? Here's the culprit, combatChangeHealth game.cpp:
Code:
        if (!target->isAttackable()) {
            if (!target->isInGhostMode()) {
                addMagicEffect(targetPos, CONST_ME_POFF);
            }
            return true;
        }

        Player* attackerPlayer;
        if (attacker) {
            attackerPlayer = attacker->getPlayer();
        } else {
            attackerPlayer = nullptr;
        }

        Player* targetPlayer = target->getPlayer();
        if (attackerPlayer && targetPlayer && attackerPlayer->getSkull() == SKULL_BLACK && attackerPlayer->getSkullClient(targetPlayer) == SKULL_NONE) {
            return false;
        }

        if (targetPlayer) {    // only custom part
            if (targetPlayer->hasCondition(CONDITION_LOGINPROTECTION)) {
                damage.primary.value = 0;
                damage.secondary.value = 0;
            }
        }    // only custom part

        damage.primary.value = std::abs(damage.primary.value);
        damage.secondary.value = std::abs(damage.secondary.value);

        TextMessage message;
        message.position = targetPos;

        if (!isEvent) {
            g_events->eventCreatureOnDrainHealth(target, attacker, damage.primary.type, damage.primary.value, damage.secondary.type, damage.secondary.value, message.primary.color, message.secondary.color);
        }
        int32_t healthChange = damage.primary.value + damage.secondary.value;
        if (healthChange == 0) {
            return true;
        }
      
        SpectatorHashSet spectators;
        map.getSpectators(spectators, targetPos, true, true);

        if (damage.critical) {
            addMagicEffect(spectators, targetPos, CONST_ME_CRITICAL_DAMAGE);
        }

        if (target->hasCondition(CONDITION_MANASHIELD) && damage.primary.type != COMBAT_UNDEFINEDDAMAGE) { <-- NULL Dereference here
 
Last edited:
Back
Top