@@ -99,17 +99,27 @@ ps_root_readerrorcb(struct psr_ctx *psr_ctx)
9999 if (eloop_waitfd (fd ) == -1 )
100100 PSR_ERROR (errno );
101101
102+ /* We peek at the psr_error structure to tell us how much of a buffer
103+ * we need to read the whole packet. */
102104 len = recvmsg (fd , & msg , MSG_PEEK | MSG_WAITALL );
103105 if (len == -1 )
104106 PSR_ERROR (errno );
105- else if ((size_t )len < sizeof (* psr_error ))
107+
108+ /* After this point, we MUST do another recvmsg even on a failure
109+ * to remove the message after peeking. */
110+ if ((size_t )len < sizeof (* psr_error ))
106111 goto recv ;
107112
108113 if (psr_ctx -> psr_usemdata &&
109114 psr_error -> psr_datalen > psr_ctx -> psr_mdatalen )
110115 {
111116 void * d = realloc (psr_ctx -> psr_mdata , psr_error -> psr_datalen );
112117
118+ /* If we failed to malloc then psr_mdatalen will be smaller
119+ * than psr_datalen.
120+ * The following recvmsg will get MSG_TRUNC so the malloc error
121+ * will be reported there but more importantly the
122+ * message will be correctly discarded from the queue. */
113123 if (d != NULL ) {
114124 psr_ctx -> psr_mdata = d ;
115125 psr_ctx -> psr_mdatalen = psr_error -> psr_datalen ;
@@ -118,7 +128,10 @@ ps_root_readerrorcb(struct psr_ctx *psr_ctx)
118128 if (psr_error -> psr_datalen != 0 ) {
119129 if (psr_ctx -> psr_usemdata ) {
120130 iov [1 ].iov_base = psr_ctx -> psr_mdata ;
121- iov [1 ].iov_len = psr_ctx -> psr_mdatalen ;
131+ /* psr_mdatalen could be smaller then psr_datalen
132+ * if the above malloc failed. */
133+ iov [1 ].iov_len =
134+ MIN (psr_ctx -> psr_mdatalen , psr_ctx -> psr_datalen );
122135 } else {
123136 iov [1 ].iov_base = psr_ctx -> psr_data ;
124137 iov [1 ].iov_len = psr_ctx -> psr_datalen ;
0 commit comments