# HG changeset patch # User Paper # Date 1718793145 14400 # Node ID d260549151d63e8ed017b53e53616fbfd49cc2b6 # Parent 5098387a3a46e4cb4605022d6782bc5a6427a4a7 dep/animone: fix undefined behavior, get correct length value diff -r 5098387a3a46 -r d260549151d6 dep/animone/src/win/x11.cc --- a/dep/animone/src/win/x11.cc Wed Jun 19 06:11:38 2024 -0400 +++ b/dep/animone/src/win/x11.cc Wed Jun 19 06:32:25 2024 -0400 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -32,12 +33,21 @@ namespace animone::internal::x11 { +template +struct XcbDestructor { + using pointer = T*; + void operator()(pointer t) const { std::free(t); }; +}; + +template +using XcbPtr = std::unique_ptr>; + static bool GetAllTopLevelWindowsEWMH(xcb_connection_t* connection, const std::vector& roots, std::set& result) { const xcb_atom_t Atom__NET_CLIENT_LIST = [connection] { static constexpr std::string_view name = "_NET_CLIENT_LIST"; xcb_intern_atom_cookie_t cookie = ::xcb_intern_atom(connection, true, name.size(), name.data()); - std::unique_ptr reply(::xcb_intern_atom_reply(connection, cookie, NULL)); + XcbPtr reply(::xcb_intern_atom_reply(connection, cookie, NULL)); xcb_atom_t atom = reply->atom; @@ -55,11 +65,11 @@ cookies.push_back(::xcb_get_property(connection, 0, root, Atom__NET_CLIENT_LIST, XCB_ATOM_ANY, 0L, UINT_MAX)); for (const auto& cookie : cookies) { - std::unique_ptr reply(::xcb_get_property_reply(connection, cookie, NULL)); + XcbPtr reply(::xcb_get_property_reply(connection, cookie, NULL)); if (reply) { xcb_window_t* value = reinterpret_cast(::xcb_get_property_value(reply.get())); - int len = ::xcb_get_property_value_length(reply.get()); + int len = ::xcb_get_property_value_length(reply.get()) / sizeof(xcb_window_t); for (size_t i = 0; i < len; i++) result.insert(value[i]); @@ -90,7 +100,7 @@ cookies.push_back(::xcb_query_tree(connection, windows[i])); for (const auto& cookie : cookies) { - std::unique_ptr query_tree_reply(::xcb_query_tree_reply(connection, cookie, NULL)); + XcbPtr query_tree_reply(::xcb_query_tree_reply(connection, cookie, NULL)); xcb_window_t* tree_children = ::xcb_query_tree_children(query_tree_reply.get()); int tree_children_len = ::xcb_query_tree_children_length(query_tree_reply.get()); @@ -103,8 +113,7 @@ ::xcb_get_property(connection, 0, tree_children[i], Atom_WM_STATE, Atom_WM_STATE, 0, 0)); for (int i = 0; i < tree_children_len; i++) { - std::unique_ptr get_property_reply( - ::xcb_get_property_reply(connection, state_property_cookies[i], NULL)); + XcbPtr get_property_reply(::xcb_get_property_reply(connection, state_property_cookies[i], NULL)); /* X11 is unfriendly here. what this means is "did the property exist?" */ if (get_property_reply->format || get_property_reply->type || get_property_reply->length) { @@ -135,10 +144,10 @@ xcb_atom_t Atom_WM_STATE = [connection] { static constexpr std::string_view name = "WM_STATE"; xcb_intern_atom_cookie_t cookie = ::xcb_intern_atom(connection, true, name.size(), name.data()); - xcb_intern_atom_reply_t* reply = ::xcb_intern_atom_reply(connection, cookie, NULL); + XcbPtr reply(::xcb_intern_atom_reply(connection, cookie, NULL)); xcb_atom_t atom = reply->atom; - free(reply); + return atom; }(); if (Atom_WM_STATE == XCB_ATOM_NONE) @@ -203,8 +212,7 @@ win.id = window_cookie.window; { /* Class name */ - std::unique_ptr reply( - ::xcb_get_property_reply(connection, window_cookie.class_property_cookie, NULL)); + XcbPtr reply(::xcb_get_property_reply(connection, window_cookie.class_property_cookie, NULL)); if (reply && reply->format == 8) { const char* data = reinterpret_cast(::xcb_get_property_value(reply.get())); @@ -218,8 +226,7 @@ } { /* Title text */ - std::unique_ptr reply( - ::xcb_get_property_reply(connection, window_cookie.name_property_cookie, NULL)); + XcbPtr reply(::xcb_get_property_reply(connection, window_cookie.name_property_cookie, NULL)); if (reply) { const char* data = reinterpret_cast(::xcb_get_property_value(reply.get())); @@ -231,8 +238,7 @@ Process proc = {0}; { /* PID */ - std::unique_ptr reply( - ::xcb_res_query_client_ids_reply(connection, window_cookie.pid_property_cookie, NULL)); + XcbPtr reply(::xcb_res_query_client_ids_reply(connection, window_cookie.pid_property_cookie, NULL)); if (reply) { xcb_res_client_id_value_iterator_t it = ::xcb_res_query_client_ids_ids_iterator(reply.get());