mirror of https://github.com/axmolengine/axmol.git
Fix out of range access in Label (#18789)
Out of range occurred in some condition when using `Label` with its `getLetter()` member function. `Label::recordPlaceholderInfo()` member function is called for new line (\n) letter in `Label::multilineTextWrap()`, but the function doesn't set `_lettersInfo[letterIndex].lineIndex`. But `lineIndex` is used in `Label::updateLabelLetters()` even if letter is new line. This change checks `letterInfo.valid` to avoid accessing `_linesOffsetX[letterInfo.lineIndex]` for invalid (i.e. `NewLine`) letter.
This commit is contained in:
parent
dfa0360d99
commit
aacec550c9
|
@ -766,30 +766,36 @@ void Label::updateLabelLetters()
|
|||
else
|
||||
{
|
||||
auto& letterInfo = _lettersInfo[letterIndex];
|
||||
auto& letterDef = _fontAtlas->_letterDefinitions[letterInfo.utf32Char];
|
||||
uvRect.size.height = letterDef.height;
|
||||
uvRect.size.width = letterDef.width;
|
||||
uvRect.origin.x = letterDef.U;
|
||||
uvRect.origin.y = letterDef.V;
|
||||
|
||||
auto batchNode = _batchNodes.at(letterDef.textureID);
|
||||
letterSprite->setTextureAtlas(batchNode->getTextureAtlas());
|
||||
letterSprite->setTexture(_fontAtlas->getTexture(letterDef.textureID));
|
||||
if (letterDef.width <= 0.f || letterDef.height <= 0.f)
|
||||
if (letterInfo.valid)
|
||||
{
|
||||
letterSprite->setTextureAtlas(nullptr);
|
||||
auto& letterDef = _fontAtlas->_letterDefinitions[letterInfo.utf32Char];
|
||||
uvRect.size.height = letterDef.height;
|
||||
uvRect.size.width = letterDef.width;
|
||||
uvRect.origin.x = letterDef.U;
|
||||
uvRect.origin.y = letterDef.V;
|
||||
|
||||
auto batchNode = _batchNodes.at(letterDef.textureID);
|
||||
letterSprite->setTextureAtlas(batchNode->getTextureAtlas());
|
||||
letterSprite->setTexture(_fontAtlas->getTexture(letterDef.textureID));
|
||||
if (letterDef.width <= 0.f || letterDef.height <= 0.f)
|
||||
{
|
||||
letterSprite->setTextureAtlas(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
letterSprite->setTextureRect(uvRect, false, uvRect.size);
|
||||
letterSprite->setTextureAtlas(_batchNodes.at(letterDef.textureID)->getTextureAtlas());
|
||||
letterSprite->setAtlasIndex(_lettersInfo[letterIndex].atlasIndex);
|
||||
}
|
||||
|
||||
auto px = letterInfo.positionX + letterDef.width / 2 + _linesOffsetX[letterInfo.lineIndex];
|
||||
auto py = letterInfo.positionY - letterDef.height / 2 + _letterOffsetY;
|
||||
letterSprite->setPosition(px, py);
|
||||
}
|
||||
else
|
||||
{
|
||||
letterSprite->setTextureRect(uvRect, false, uvRect.size);
|
||||
letterSprite->setTextureAtlas(_batchNodes.at(letterDef.textureID)->getTextureAtlas());
|
||||
letterSprite->setAtlasIndex(_lettersInfo[letterIndex].atlasIndex);
|
||||
letterSprite->setTextureAtlas(nullptr);
|
||||
}
|
||||
|
||||
auto px = letterInfo.positionX + letterDef.width / 2 + _linesOffsetX[letterInfo.lineIndex];
|
||||
auto py = letterInfo.positionY - letterDef.height / 2 + _letterOffsetY;
|
||||
letterSprite->setPosition(px, py);
|
||||
|
||||
this->updateLetterSpriteScale(letterSprite);
|
||||
++it;
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ NewLabelTests::NewLabelTests()
|
|||
ADD_TEST_CASE(LabelIssue16717);
|
||||
ADD_TEST_CASE(LabelIssueLineGap);
|
||||
ADD_TEST_CASE(LabelIssue17902);
|
||||
ADD_TEST_CASE(LabelLetterColorsTest);
|
||||
};
|
||||
|
||||
LabelFNTColorAndOpacity::LabelFNTColorAndOpacity()
|
||||
|
@ -3567,4 +3568,35 @@ std::string LabelIssue17902::subtitle() const
|
|||
return "";
|
||||
}
|
||||
|
||||
//
|
||||
// LabelLetterColorsTest
|
||||
//
|
||||
LabelLetterColorsTest::LabelLetterColorsTest() {
|
||||
auto center = VisibleRect::center();
|
||||
|
||||
auto label = Label::createWithTTF("", "fonts/arial.ttf", 24);
|
||||
label->setPosition(center.x, center.y);
|
||||
addChild(label);
|
||||
|
||||
label->setString("1\n2\n3");
|
||||
setLetterColors(label, Color3B::RED);
|
||||
|
||||
label->setString("abcd\ne"); // Must not crash at here.
|
||||
}
|
||||
|
||||
std::string LabelLetterColorsTest::title() const {
|
||||
return "Test for letter colors";
|
||||
}
|
||||
|
||||
std::string LabelLetterColorsTest::subtitle() const {
|
||||
return "Should not crash!";
|
||||
}
|
||||
|
||||
void LabelLetterColorsTest::setLetterColors(cocos2d::Label* label, const cocos2d::Color3B& color) {
|
||||
int n = label->getStringLength();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
Sprite* letter = label->getLetter(i);
|
||||
if (letter != nullptr)
|
||||
letter->setColor(color);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -980,4 +980,17 @@ public:
|
|||
virtual std::string subtitle() const override;
|
||||
};
|
||||
|
||||
class LabelLetterColorsTest : public AtlasDemoNew {
|
||||
public:
|
||||
CREATE_FUNC(LabelLetterColorsTest);
|
||||
|
||||
LabelLetterColorsTest();
|
||||
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
|
||||
private:
|
||||
static void setLetterColors(cocos2d::Label* label, const cocos2d::Color3B& color);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue