Fix out-of-bounds table read in wxMBConvUTF7::ToWChar() In wxMBConvUTF7::ToWChar() the value of the byte after '+' was cast to "unsigned", which meant that on the platforms with signed bytes values greater than 0x80 were sign-extended to a ~4GiB index which was (way) out of bounds for a 256-entry table. Fix the code by casting to "unsigned char", like the cc lookup just above already does. Closes #26517.
Add wxSizer::DetachItem() Unlike the existing Detach(), this function doesn't delete wxSizerItem itself, allowing to add it back to this or another sizer later. Closes #26512.
| ... | ... | @@ -617,6 +617,8 @@ public: |
| 617 | 617 | virtual bool Detach( wxSizer *sizer );
|
| 618 | 618 | virtual bool Detach( int index );
|
| 619 | 619 | |
| 620 | + wxNODISCARD virtual wxSizerItem *DetachItem(size_t index);
|
|
| 621 | + |
|
| 620 | 622 | virtual bool Replace( wxWindow *oldwin, wxWindow *newwin, bool recursive = false );
|
| 621 | 623 | virtual bool Replace( wxSizer *oldsz, wxSizer *newsz, bool recursive = false );
|
| 622 | 624 | virtual bool Replace( size_t index, wxSizerItem *newitem );
|
| ... | ... | @@ -440,16 +440,39 @@ public: |
| 440 | 440 | virtual bool Detach(wxSizer* sizer);
|
| 441 | 441 | |
| 442 | 442 | /**
|
| 443 | - Detach an item at position @a index from the sizer without destroying it.
|
|
| 443 | + Detach the child sizer or window in item at position @a index without
|
|
| 444 | + destroying the child object.
|
|
| 444 | 445 | |
| 445 | 446 | This method does not cause any layout or resizing to take place, call Layout()
|
| 446 | 447 | to update the layout "on screen" after detaching a child from the sizer.
|
| 448 | + |
|
| 447 | 449 | Returns @true if the child item was found and detached, @false otherwise.
|
| 448 | 450 | |
| 451 | + Note that the sizer item containing the child sizer or window is
|
|
| 452 | + deleted by this function, see DetachItem() if you want to prevent this
|
|
| 453 | + from happening.
|
|
| 454 | + |
|
| 449 | 455 | @see Remove()
|
| 450 | 456 | */
|
| 451 | 457 | virtual bool Detach(int index);
|
| 452 | 458 | |
| 459 | + /**
|
|
| 460 | + Detach the item at position @a index without destroying it.
|
|
| 461 | + |
|
| 462 | + This method does not cause any layout or resizing to take place, call Layout()
|
|
| 463 | + to update the layout "on screen" after detaching a child from the sizer.
|
|
| 464 | + |
|
| 465 | + Returns the item if it was found and detached, @nullptr otherwise.
|
|
| 466 | + |
|
| 467 | + The caller takes ownership of the returned pointer, i.e. must either
|
|
| 468 | + delete it or add it back to this or another sizer later.
|
|
| 469 | + |
|
| 470 | + @see Remove(), Add()
|
|
| 471 | + |
|
| 472 | + @since 3.3.3
|
|
| 473 | + */
|
|
| 474 | + virtual wxSizerItem *DetachItem(size_t index);
|
|
| 475 | + |
|
| 453 | 476 | /**
|
| 454 | 477 | Tell the sizer to resize the @a window so that its client area matches the
|
| 455 | 478 | sizer's minimal size (ComputeFittingClientSize() is called to determine it).
|
| ... | ... | @@ -1099,6 +1099,23 @@ bool wxSizer::Detach( int index ) |
| 1099 | 1099 | return true;
|
| 1100 | 1100 | }
|
| 1101 | 1101 | |
| 1102 | +wxSizerItem *wxSizer::DetachItem(size_t index)
|
|
| 1103 | +{
|
|
| 1104 | + const auto node = GetChildNode(index);
|
|
| 1105 | + if ( !node )
|
|
| 1106 | + return nullptr;
|
|
| 1107 | + |
|
| 1108 | + wxSizerItem *item = node->GetData();
|
|
| 1109 | + |
|
| 1110 | + wxWindow *window = item->GetWindow();
|
|
| 1111 | + if ( window != nullptr )
|
|
| 1112 | + window->SetContainingSizer(nullptr);
|
|
| 1113 | + |
|
| 1114 | + m_children.Erase( node );
|
|
| 1115 | + |
|
| 1116 | + return item;
|
|
| 1117 | +}
|
|
| 1118 | + |
|
| 1102 | 1119 | bool wxSizer::Replace( wxWindow *oldwin, wxWindow *newwin, bool recursive )
|
| 1103 | 1120 | {
|
| 1104 | 1121 | wxASSERT_MSG( oldwin, wxT("Replacing null window") );
|
| ... | ... | @@ -702,7 +702,7 @@ size_t wxMBConvUTF7::ToWChar(wchar_t *dst, size_t dstLen, |
| 702 | 702 | len++;
|
| 703 | 703 | src++;
|
| 704 | 704 | }
|
| 705 | - else if ( utf7unb64[(unsigned)*src] == 0xff )
|
|
| 705 | + else if ( utf7unb64[(unsigned char)*src] == 0xff )
|
|
| 706 | 706 | {
|
| 707 | 707 | // empty encoded chunks are not allowed
|
| 708 | 708 | if ( !len )
|
| ... | ... | @@ -1495,4 +1495,9 @@ TEST_CASE("wxMBConv::cMB2WC", "[mbconv][mb2wc]") |
| 1495 | 1495 | CHECK( wxConvUTF7.cMB2WC("").length() == 0 );
|
| 1496 | 1496 | CHECK( wxConvUTF7.cMB2WC(wxCharBuffer()).length() == 0 );
|
| 1497 | 1497 | CHECK( wxConvUTF7.cMB2WC("+AKM-").length() == 1 );
|
| 1498 | + |
|
| 1499 | + // A non-ASCII byte right after the shift character used to be read past
|
|
| 1500 | + // the end of the base-64 decoding table (signed char index), now it's
|
|
| 1501 | + // just rejected as an invalid encoded chunk.
|
|
| 1502 | + CHECK( wxConvUTF7.cMB2WC("+\xc3").length() == 0 );
|
|
| 1498 | 1503 | } |
| ... | ... | @@ -448,6 +448,40 @@ TEST_CASE_METHOD(BoxSizerTestCase, "BoxSizer::Replace", "[sizer]") |
| 448 | 448 | m_sizer->Replace(0, new wxSizerItem(new wxWindow(m_win, wxID_ANY)));
|
| 449 | 449 | }
|
| 450 | 450 | |
| 451 | +TEST_CASE_METHOD(BoxSizerTestCase, "Sizer::DetachItem", "[sizer]")
|
|
| 452 | +{
|
|
| 453 | + wxSizerItem *item = nullptr;
|
|
| 454 | + |
|
| 455 | + SECTION("Spacer")
|
|
| 456 | + {
|
|
| 457 | + item = new wxSizerItem(0, 0);
|
|
| 458 | + }
|
|
| 459 | + |
|
| 460 | + SECTION("Sizer")
|
|
| 461 | + {
|
|
| 462 | + item = new wxSizerItem(new wxBoxSizer(wxVERTICAL));
|
|
| 463 | + }
|
|
| 464 | + |
|
| 465 | + SECTION("Window")
|
|
| 466 | + {
|
|
| 467 | + item = new wxSizerItem(new wxWindow(m_win, wxID_ANY));
|
|
| 468 | + }
|
|
| 469 | + |
|
| 470 | + m_sizer->Add(item);
|
|
| 471 | + |
|
| 472 | + // Test re-insertion
|
|
| 473 | + auto *detached = m_sizer->DetachItem(0);
|
|
| 474 | + CHECK( item == detached );
|
|
| 475 | + |
|
| 476 | + m_sizer->Insert(0, detached);
|
|
| 477 | + |
|
| 478 | + // Test deletion after detach.
|
|
| 479 | + detached = m_sizer->DetachItem(0);
|
|
| 480 | + CHECK( item == detached );
|
|
| 481 | + |
|
| 482 | + delete detached;
|
|
| 483 | +}
|
|
| 484 | + |
|
| 451 | 485 | TEST_CASE("Sizer::CombineFlags", "[sizer]")
|
| 452 | 486 | {
|
| 453 | 487 | // This is a compile-time test which simply verifies that we can combine
|
—
View it on GitLab.
You're receiving this email because of your account on gitlab.com. Manage all notifications · Help