changeset 336:d260549151d6

dep/animone: fix undefined behavior, get correct length value
author Paper <paper@paper.us.eu.org>
date Wed, 19 Jun 2024 06:32:25 -0400
parents 5098387a3a46
children a7d4e5107531
files dep/animone/src/win/x11.cc
diffstat 1 files changed, 20 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- 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 <climits>
 #include <cstdint>
 #include <cstring>
+#include <cstdlib>
 #include <set>
 #include <string>
 #include <memory>
@@ -32,12 +33,21 @@
 
 namespace animone::internal::x11 {
 
+template<typename T>
+struct XcbDestructor {
+	using pointer = T*;
+	void operator()(pointer t) const { std::free(t); };
+};
+
+template<typename T>
+using XcbPtr = std::unique_ptr<T, XcbDestructor<T>>;
+
 static bool GetAllTopLevelWindowsEWMH(xcb_connection_t* connection, const std::vector<xcb_window_t>& roots,
                                       std::set<xcb_window_t>& 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<xcb_intern_atom_reply_t> reply(::xcb_intern_atom_reply(connection, cookie, NULL));
+		XcbPtr<xcb_intern_atom_reply_t> 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<xcb_get_property_reply_t> reply(::xcb_get_property_reply(connection, cookie, NULL));
+		XcbPtr<xcb_get_property_reply_t> reply(::xcb_get_property_reply(connection, cookie, NULL));
 
 		if (reply) {
 			xcb_window_t* value = reinterpret_cast<xcb_window_t*>(::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<xcb_query_tree_reply_t> query_tree_reply(::xcb_query_tree_reply(connection, cookie, NULL));
+		XcbPtr<xcb_query_tree_reply_t> 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<xcb_get_property_reply_t> get_property_reply(
-			    ::xcb_get_property_reply(connection, state_property_cookies[i], NULL));
+			XcbPtr<xcb_get_property_reply_t> 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<xcb_intern_atom_reply_t> 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<xcb_get_property_reply_t> reply(
-			    ::xcb_get_property_reply(connection, window_cookie.class_property_cookie, NULL));
+			XcbPtr<xcb_get_property_reply_t> reply(::xcb_get_property_reply(connection, window_cookie.class_property_cookie, NULL));
 
 			if (reply && reply->format == 8) {
 				const char* data = reinterpret_cast<const char*>(::xcb_get_property_value(reply.get()));
@@ -218,8 +226,7 @@
 		}
 		{
 			/* Title text */
-			std::unique_ptr<xcb_get_property_reply_t> reply(
-			    ::xcb_get_property_reply(connection, window_cookie.name_property_cookie, NULL));
+			XcbPtr<xcb_get_property_reply_t> reply(::xcb_get_property_reply(connection, window_cookie.name_property_cookie, NULL));
 
 			if (reply) {
 				const char* data = reinterpret_cast<const char*>(::xcb_get_property_value(reply.get()));
@@ -231,8 +238,7 @@
 		Process proc = {0};
 		{
 			/* PID */
-			std::unique_ptr<xcb_res_query_client_ids_reply_t> reply(
-			    ::xcb_res_query_client_ids_reply(connection, window_cookie.pid_property_cookie, NULL));
+			XcbPtr<xcb_res_query_client_ids_reply_t> 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());