Fix zero-length RAW_RR losing type metadata during parsing (#1129)

ares_dns_parse_rr_raw_rr() returned early when rdlength==0 without
setting ARES_RR_RAW_RR_TYPE, so the record's type was lost (left as 0).
Move the type assignment to the top of the function so it is set
unconditionally, before the zero-length early return.

Add test with a hand-crafted DNS packet containing a zero-length RAW_RR
with type 65432, verifying the type survives the parse.

---------

Signed-off-by: David Hotham (@dimbleby)
diff --git a/src/lib/record/ares_dns_parse.c b/src/lib/record/ares_dns_parse.c
index 01f3f43..6430e7f 100644
--- a/src/lib/record/ares_dns_parse.c
+++ b/src/lib/record/ares_dns_parse.c
@@ -768,6 +768,12 @@
   ares_status_t  status;
   unsigned char *bytes = NULL;
 
+  /* Can't fail */
+  status = ares_dns_rr_set_u16(rr, ARES_RR_RAW_RR_TYPE, raw_type);
+  if (status != ARES_SUCCESS) {
+    return status;
+  }
+
   if (rdlength == 0) {
     return ARES_SUCCESS;
   }
@@ -777,13 +783,6 @@
     return status;
   }
 
-  /* Can't fail */
-  status = ares_dns_rr_set_u16(rr, ARES_RR_RAW_RR_TYPE, raw_type);
-  if (status != ARES_SUCCESS) {
-    ares_free(bytes);
-    return status;
-  }
-
   status = ares_dns_rr_set_bin_own(rr, ARES_RR_RAW_RR_DATA, bytes, rdlength);
   if (status != ARES_SUCCESS) {
     ares_free(bytes);
diff --git a/test/ares-test-internal.cc b/test/ares-test-internal.cc
index 11b7c14..4b03b0d 100644
--- a/test/ares-test-internal.cc
+++ b/test/ares-test-internal.cc
@@ -1574,6 +1574,47 @@
   ares_socket_t s;
 } test_htable_asvp_t;
 
+TEST_F(LibraryTest, ZeroLengthRawRrKeepsType) {
+  ares_dns_record_t *parsed = NULL;
+  ares_dns_rr_t     *rr     = NULL;
+
+  /* Hand-crafted minimal DNS response with a zero-length RAW_RR.
+   * Header: id=0x1234, QR=1 RD=1 RA=1, QDCOUNT=1, ANCOUNT=1
+   * Question: \x07example\x03com\x00, type A (1), class IN (1)
+   * Answer:   \xc0\x0c (name ptr), type=0xFF98 (65432), class IN,
+   *           TTL=300, RDLENGTH=0 */
+  const unsigned char pkt[] = {
+    /* Header */
+    0x12, 0x34,  /* ID */
+    0x81, 0x80,  /* Flags: QR=1, RD=1, RA=1 */
+    0x00, 0x01,  /* QDCOUNT=1 */
+    0x00, 0x01,  /* ANCOUNT=1 */
+    0x00, 0x00,  /* NSCOUNT=0 */
+    0x00, 0x00,  /* ARCOUNT=0 */
+    /* Question: example.com, type A, class IN */
+    0x07, 'e','x','a','m','p','l','e',
+    0x03, 'c','o','m',
+    0x00,
+    0x00, 0x01,  /* QTYPE=A */
+    0x00, 0x01,  /* QCLASS=IN */
+    /* Answer RR: example.com (compressed), type 65432, class IN, TTL 300 */
+    0xc0, 0x0c,  /* Name pointer */
+    0xff, 0x98,  /* TYPE=65432 */
+    0x00, 0x01,  /* CLASS=IN */
+    0x00, 0x00, 0x01, 0x2c,  /* TTL=300 */
+    0x00, 0x00   /* RDLENGTH=0 */
+  };
+
+  EXPECT_EQ(ARES_SUCCESS,
+    ares_dns_parse(pkt, sizeof(pkt), 0, &parsed));
+  EXPECT_EQ(1, ares_dns_record_rr_cnt(parsed, ARES_SECTION_ANSWER));
+  rr = ares_dns_record_rr_get(parsed, ARES_SECTION_ANSWER, 0);
+  EXPECT_EQ(ARES_REC_TYPE_RAW_RR, ares_dns_rr_get_type(rr));
+  EXPECT_EQ(65432, ares_dns_rr_get_u16(rr, ARES_RR_RAW_RR_TYPE));
+
+  ares_dns_record_destroy(parsed);
+}
+
 TEST_F(LibraryTest, RawRrTypeTostrFromstrRoundtrip) {
   const char         *str;
   ares_dns_rec_type_t qtype = (ares_dns_rec_type_t)0;