Codebase list wayland / 446047e
tests: add request_bogus_size This attempts to reproduce the error conditions from https://gitlab.freedesktop.org/wayland/wayland/issues/52 and make it crash. While the crash was repeatable in my tests, it depends on garbage on stack leading to access of invalid memory, which is not guaranteed. This is a FAIL_TEST, so that the following fix commit can be verified. Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com> Reviewed-by: Simon Ser <contact@emersion.fr> Pekka Paalanen 5 years ago
1 changed file(s) with 87 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
751751
752752 display_destroy(d);
753753 }
754
755 /** Raw read from socket expecting wl_display.error
756 *
757 * \param sockfd The socket to read from.
758 * \param expected_error The expected wl_display error code.
759 *
760 * Reads the socket and manually parses one message, expecting it to be a
761 * wl_display.error with the wl_display as the originating object.
762 * Asserts that the received error code is expected_error.
763 */
764 static void
765 expect_error_recv(int sockfd, uint32_t expected_error)
766 {
767 uint32_t buf[1024];
768 ssize_t slen;
769 uint32_t opcode;
770 int str_len;
771
772 slen = recv(sockfd, buf, sizeof buf, 0);
773 assert(slen >= 2 * (ssize_t)sizeof (uint32_t));
774 opcode = buf[1] & 0xffff;
775 fprintf(stderr, "Received %zd bytes, object %u, opcode %u\n",
776 slen, buf[0], opcode);
777
778 /* check error event */
779 assert(buf[0] == 1);
780 assert(opcode == WL_DISPLAY_ERROR);
781
782 str_len = buf[4];
783 assert(str_len > 0);
784 assert(str_len <= slen - 5 * (ssize_t)sizeof (uint32_t));
785 fprintf(stderr, "Error event on object %u, code %u, message \"%*s\"\n",
786 buf[2], buf[3], str_len, (const char *)&buf[5]);
787
788 assert(buf[3] == expected_error);
789 }
790
791 /* A test for https://gitlab.freedesktop.org/wayland/wayland/issues/52
792 * trying to provoke a read from uninitialized memory in
793 * wl_connection_demarshal() for sender_id and opcode.
794 *
795 * This test might not fail as is even with #52 unfixed, since there is no way
796 * to detect what happens and the crash with zero size depends on stack content.
797 * However, running under Valgrind would point out invalid reads and use of
798 * uninitialized values.
799 */
800 FAIL_TEST(request_bogus_size)
801 {
802 struct wl_display *display;
803 struct wl_client *client;
804 int s[2];
805 uint32_t msg[3];
806 int bogus_size;
807
808 test_set_timeout(1);
809
810 /*
811 * The manufactured message has real size 12. Test all bogus sizes
812 * smaller than that, and zero as the last one since wl_closure_init
813 * handles zero specially and having garbage in the stack makes it more
814 * likely to crash in wl_connection_demarshal.
815 */
816 for (bogus_size = 11; bogus_size >= 0; bogus_size--) {
817 fprintf(stderr, "* bogus size %d\n", bogus_size);
818
819 assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
820 display = wl_display_create();
821 assert(display);
822 client = wl_client_create(display, s[0]);
823 assert(client);
824
825 /* manufacture a request that lies about its size */
826 msg[0] = 1; /* sender id: wl_display */
827 msg[1] = (bogus_size << 16) | WL_DISPLAY_SYNC; /* size and opcode */
828 msg[2] = 2; /* sync argument: new_id for wl_callback */
829
830 assert(send(s[1], msg, sizeof msg, 0) == sizeof msg);
831
832 wl_event_loop_dispatch(wl_display_get_event_loop(display), 0);
833
834 expect_error_recv(s[1], WL_DISPLAY_ERROR_INVALID_METHOD);
835
836 /* Do not wl_client_destroy, the error already caused it. */
837 close(s[1]);
838 wl_display_destroy(display);
839 }
840 }