summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2022-09-22 12:41:23 -0400
committerRich Felker <dalias@aerifal.cx>2022-09-22 12:41:23 -0400
commite2e9517607f67c1e23c059769b19bf4270d22123 (patch)
treef8d4c7cc836e5387811a7c8e27c03dedbc927990 /src
parentc87d75f2aa6fde49a99cf3287e535a14f354f781 (diff)
downloadmusl-e2e9517607f67c1e23c059769b19bf4270d22123.tar.gz
res_send: use a temp buffer if caller's buffer is under 512 bytes
for extremely small buffer sizes, the DNS query core in __res_msend may malfunction completely, being unable to get even the headers to determine the response code. but there is also a problem for reasonable sizes under 512 bytes: __res_msend is unable to determine if the udp answer was truncated at the recv layer, in which case it may be incomplete, and res_send is then unable to honor its contract to return the length of the full, non-truncated answer. at present, res_send does not honor that contract anyway when the full answer would exceed 512 bytes, since there is no tcp fallback, but this change at least makes it consistent in a context where this is the only "full answer" to be had.
Diffstat (limited to 'src')
-rw-r--r--src/network/res_send.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/network/res_send.c b/src/network/res_send.c
index ee4abf1f..9593164d 100644
--- a/src/network/res_send.c
+++ b/src/network/res_send.c
@@ -1,8 +1,16 @@
#include <resolv.h>
+#include <string.h>
int __res_send(const unsigned char *msg, int msglen, unsigned char *answer, int anslen)
{
- int r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
+ int r;
+ if (anslen < 512) {
+ unsigned char buf[512];
+ r = __res_send(msg, msglen, buf, sizeof buf);
+ if (r >= 0) memcpy(answer, buf, r < anslen ? r : anslen);
+ return r;
+ }
+ r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
return r<0 || !anslen ? -1 : anslen;
}