diff --git a/native/CHANGELOG.md b/native/CHANGELOG.md index 2244e30d9..54b7e2045 100644 --- a/native/CHANGELOG.md +++ b/native/CHANGELOG.md @@ -6,6 +6,7 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how ## Recent Changes +- `c`: Fixed several vulnerabilities in C++ and Metal C code to improve stability. [#940](https://github.com/zowe/zowex/pull/940) - **Breaking:** `c`: Refactored the backend for copying data sets to use Z/OS utilities IEBCOPY and IEBGENER. Removed `--delete-target-members` flag and added `--overwrite` flag for copying a partitioned data set to an existing partitioned data set. Removed duplicate `member_exists_in_pds` function. [#932] (https://github.com/zowe/zowex/issues/932) - `c`: Fix spool read / dynalloc error via optimization assignments. [#945](https://github.com/zowe/zowex/issues/945) - `c`: Updated `zut_read_input` so that all tests pass on `zowex`. Now there is no specific handling for line-based TTY input so that data is more consistently preserved.[#953](https://github.com/zowe/zowex/pull/953) diff --git a/native/c/commands/uss.cpp b/native/c/commands/uss.cpp index 3e044213f..5298090bb 100644 --- a/native/c/commands/uss.cpp +++ b/native/c/commands/uss.cpp @@ -213,6 +213,12 @@ int handle_uss_list(InvocationContext &context) fields.push_back(field); } + // We should have 8 fields: mode, links, user, group, size, filetag, mtime, name + if (fields.size() < 8) + { + continue; + } + entry->set("mode", str(fields[0])); entry->set("links", i64(atoi(fields[1].c_str()))); entry->set("user", str(fields[2])); diff --git a/native/c/zam.c b/native/c/zam.c index beac20c97..24cb2f935 100644 --- a/native/c/zam.c +++ b/native/c/zam.c @@ -63,7 +63,7 @@ static int handle_dcb_abend(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc, const char *P if (0 == diag->e_msg_len) { strcpy(diag->service_name, operation); - diag->e_msg_len = sprintf(diag->e_msg, "DCB abend during %s for %8.8s data set: %44.44s", + ZDIAG_SET_MSG(diag, "DCB abend during %.16s for %8.8s data set: %44.44s", operation, ioc->ddname, ioc->jfcb.jfcbdsnm); diag->detail_rc = ZDS_RTNCD_DCB_ABEND_ERROR; } @@ -78,7 +78,7 @@ static int validate_jfcb_attributes(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) if (ioc->jfcb.jfcbind1 != jfcpds) { - diag->e_msg_len = sprintf(diag->e_msg, "DDname: %8.8s data set: %44.44s is not a PDS: %X", ioc->dcb.dcbddnam, ioc->jfcb.jfcbdsnm, ioc->jfcb.jfcbind1); + ZDIAG_SET_MSG(diag, "DDname: %8.8s data set: %44.44s is not a PDS: %X", ioc->dcb.dcbddnam, ioc->jfcb.jfcbdsnm, ioc->jfcb.jfcbind1); diag->detail_rc = ZDS_RTNCD_UNSUPPORTED_DATA_SET; return RTNCD_FAILURE; } @@ -86,7 +86,7 @@ static int validate_jfcb_attributes(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) // ensure member name (e.g. is a partitioned data set) if (ioc->jfcb.jfcbelnm[0] == ' ') { - diag->e_msg_len = sprintf(diag->e_msg, "DDname: %8.8s data set: %44.44s is not a partitioned data set: %s", ioc->dcb.dcbddnam, ioc->jfcb.jfcbdsnm, ioc->jfcb.jfcbelnm); + ZDIAG_SET_MSG(diag, "DDname: %8.8s data set: %44.44s is not a partitioned data set: %.8s", ioc->dcb.dcbddnam, ioc->jfcb.jfcbdsnm, ioc->jfcb.jfcbelnm); diag->detail_rc = ZDS_RTNCD_UNSUPPORTED_DSORG; return RTNCD_FAILURE; } @@ -107,7 +107,7 @@ static int enq_data_set(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) { diag->service_rc = rc; strcpy(diag->service_name, "ENQ"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to ENQ ddname: %8.8s data set: %44.44s rc was: %d", ioc->dcb.dcbddnam, ioc->jfcb.jfcbdsnm, rc); + ZDIAG_SET_MSG(diag, "Failed to ENQ ddname: %8.8s data set: %44.44s rc was: %d", ioc->dcb.dcbddnam, ioc->jfcb.jfcbdsnm, rc); diag->detail_rc = ZDS_RTNCD_ENQ_ERROR; return RTNCD_FAILURE; } @@ -147,7 +147,7 @@ static int get_ucb(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) if (0 == ioc->ucb) { diag->detail_rc = ZDS_RTNCD_UCB_ERROR; - diag->e_msg_len = sprintf(diag->e_msg, "Failed to get UCB for data set: %44.44s", ioc->jfcb.jfcbdsnm); + ZDIAG_SET_MSG(diag, "Failed to get UCB for data set: %44.44s", ioc->jfcb.jfcbdsnm); return RTNCD_FAILURE; } @@ -167,7 +167,7 @@ static int reserve_data_set(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) { diag->service_rc = rc; strcpy(diag->service_name, "RESERVE"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to RESERVE ddname: %8.8s data set: %44.44s rc was: %d", ioc->dcb.dcbddnam, ioc->jfcb.jfcbdsnm, rc); + ZDIAG_SET_MSG(diag, "Failed to RESERVE ddname: %8.8s data set: %44.44s rc was: %d", ioc->dcb.dcbddnam, ioc->jfcb.jfcbdsnm, rc); diag->detail_rc = ZDS_RTNCD_RESERVE_ERROR; return RTNCD_FAILURE; } @@ -184,7 +184,7 @@ static int open_data_set(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) { diag->service_rc = rc; strcpy(diag->service_name, "OPEN"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to open ddname: %8.8s for data set: %44.44s rc was: %d", ioc->dcb.dcbddnam, ioc->jfcb.jfcbdsnm, rc); + ZDIAG_SET_MSG(diag, "Failed to open ddname: %8.8s for data set: %44.44s rc was: %d", ioc->dcb.dcbddnam, ioc->jfcb.jfcbdsnm, rc); diag->detail_rc = ZDS_RTNCD_OPEN_ERROR; return RTNCD_FAILURE; } @@ -196,7 +196,7 @@ static int open_data_set(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) if (!(ioc->dcb.dcboflgs & dcbofopn)) { - diag->e_msg_len = sprintf(diag->e_msg, "Data set is not open: %44.44s", ioc->jfcb.jfcbdsnm); + ZDIAG_SET_MSG(diag, "Data set is not open: %44.44s", ioc->jfcb.jfcbdsnm); diag->detail_rc = ZDS_RTNCD_NOT_OPEN_ERROR; return RTNCD_FAILURE; } @@ -210,7 +210,7 @@ static int validate_dcb_attributes(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) if (!(ioc->dcb.dcbrecfm & (dcbrecf | dcbrecv))) { - diag->e_msg_len = sprintf(diag->e_msg, "Data set is not a fixed or variable record format: %X", ioc->dcb.dcbrecfm); + ZDIAG_SET_MSG(diag, "Data set is not a fixed or variable record format: %X", ioc->dcb.dcbrecfm); diag->detail_rc = ZDS_RTNCD_UNSUPPORTED_RECFM; return RTNCD_FAILURE; } @@ -219,7 +219,7 @@ static int validate_dcb_attributes(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) if (block_size < 1) { - diag->e_msg_len = sprintf(diag->e_msg, "Data set has less than 1 block size: %X", block_size); + ZDIAG_SET_MSG(diag, "Data set has less than 1 block size: %X", block_size); diag->detail_rc = ZDS_RTNCD_UNSUPPORTED_BLOCK_SIZE; return RTNCD_FAILURE; } @@ -231,7 +231,7 @@ static int validate_dcb_attributes(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) // Fixed-length record validation if (block_size % ioc->dcb.dcblrecl != 0) { - diag->e_msg_len = sprintf(diag->e_msg, "Data set block size is not a multiple of the record length: %d not evenly divisible by %d", ioc->dcb.dcbblksi, ioc->dcb.dcblrecl); + ZDIAG_SET_MSG(diag, "Data set block size is not a multiple of the record length: %d not evenly divisible by %d", ioc->dcb.dcbblksi, ioc->dcb.dcblrecl); diag->detail_rc = ZDS_RTNCD_INVALID_BLOCK_SIZE; return RTNCD_FAILURE; } @@ -241,7 +241,7 @@ static int validate_dcb_attributes(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) // Variable-length record validation: block size must be >= LRECL + 4 (for BDW) if (block_size < ioc->dcb.dcblrecl + sizeof(BDW)) { - diag->e_msg_len = sprintf(diag->e_msg, "Data set block size is too small for variable records: %d < %d (LRECL + 4)", block_size, ioc->dcb.dcblrecl + sizeof(BDW)); + ZDIAG_SET_MSG(diag, "Data set block size is too small for variable records: %d < %d (LRECL + 4)", block_size, ioc->dcb.dcblrecl + sizeof(BDW)); diag->detail_rc = ZDS_RTNCD_INVALID_BLOCK_SIZE; return RTNCD_FAILURE; } @@ -263,7 +263,7 @@ static int note_member(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc, NOTE_RESPONSE *PTR { diag->service_rc = rc; strcpy(diag->service_name, "NOTE"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to NOTE ddname: %8.8s data set: %44.44s rc was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rc); + ZDIAG_SET_MSG(diag, "Failed to NOTE ddname: %8.8s data set: %44.44s rc was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rc); diag->detail_rc = ZDS_RTNCD_NOTE_ERROR; } } @@ -303,7 +303,7 @@ int open_input_vsam(ZDIAG *PTR32 diag, IO_CTRL *PTR32 *PTR32 ioc, const char *PT { diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; strcpy(diag->service_name, "MODCB"); - diag->e_msg_len = sprintf(diag->e_msg, "MODCB failed rc was: %d rsn was: %d", rc, rsn); + ZDIAG_SET_MSG(diag, "MODCB failed rc was: %d rsn was: %d", rc, rsn); diag->service_rc = rc; diag->service_rsn = rsn; return RTNCD_FAILURE; @@ -314,7 +314,7 @@ int open_input_vsam(ZDIAG *PTR32 diag, IO_CTRL *PTR32 *PTR32 ioc, const char *PT { diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; strcpy(diag->service_name, "OPEN"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to open acb rc was: %d", rc); + ZDIAG_SET_MSG(diag, "Failed to open acb rc was: %d", rc); diag->service_rc = rc; return RTNCD_FAILURE; } @@ -341,7 +341,7 @@ int point_input_vsam(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc, TIME_STRUCT *time_st { diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; strcpy(diag->service_name, "CONVTOD"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to CONVTOD rc was: %d", rc); + ZDIAG_SET_MSG(diag, "Failed to CONVTOD rc was: %d", rc); diag->service_rc = rc; return rc; } @@ -358,7 +358,7 @@ int point_input_vsam(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc, TIME_STRUCT *time_st { diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; strcpy(diag->service_name, "POINT"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to POINT rc was: %d", rc); + ZDIAG_SET_MSG(diag, "Failed to POINT rc was: %d", rc); diag->service_rc = rc; return rc; } @@ -392,7 +392,7 @@ int read_input_vsam(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; strcpy(diag->service_name, "GET"); memcpy(rplrdbk, &rplp->rplfdbwd.rplfdbk, sizeof(rplrdbk)); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to GET rc was: %d, RPLRDBK was: %02X%02X%02X", rc, rplrdbk[0], rplrdbk[1], rplrdbk[2]); + ZDIAG_SET_MSG(diag, "Failed to GET rc was: %d, RPLRDBK was: %02X%02X%02X", rc, rplrdbk[0], rplrdbk[1], rplrdbk[2]); diag->service_rc = rc; return rc; } @@ -410,7 +410,7 @@ int close_input_vsam(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) { diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; strcpy(diag->service_name, "CLOSE"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to close acb rc was: %d", rc); + ZDIAG_SET_MSG(diag, "Failed to close acb rc was: %d", rc); diag->service_rc = rc; return RTNCD_FAILURE; } @@ -454,7 +454,7 @@ int open_output_bpam(ZDIAG *PTR32 diag, IO_CTRL *PTR32 *PTR32 ioc, const char *P { diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; strcpy(diag->service_name, "RDJFCB"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to read output JFCB rc was: %d", rc); + ZDIAG_SET_MSG(diag, "Failed to read output JFCB rc was: %d", rc); diag->service_rc = rc; return RTNCD_FAILURE; } @@ -559,7 +559,7 @@ static int handle_fixed_record(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc, const char if (0 != rc) { - diag->e_msg_len = sprintf(diag->e_msg, "Failed to write record rc was: %d", rc); + ZDIAG_SET_MSG(diag, "Failed to write record rc was: %d", rc); diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; diag->service_rc = rc; return RTNCD_FAILURE; @@ -607,7 +607,7 @@ static int write_variable_record(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc, const ch if (0 != rc) { - diag->e_msg_len = sprintf(diag->e_msg, "Failed to write record rc was: %d", rc); + ZDIAG_SET_MSG(diag, "Failed to write record rc was: %d", rc); diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; diag->service_rc = rc; return RTNCD_FAILURE; @@ -626,7 +626,8 @@ static void copy_variable_record(IO_CTRL *PTR32 ioc, const char *PTR32 data, int ioc->lines_written++; RDW *PTR32 rdw_ptr = (RDW * PTR32) ioc->free_location; rdw_ptr->unused = 0; - rdw_ptr->len = sprintf(ioc->free_location + sizeof(RDW), "%.*s", length, data) + sizeof(RDW); + memcpy(ioc->free_location + sizeof(RDW), data, length); + rdw_ptr->len = length + sizeof(RDW); ioc->bytes_in_buffer += rdw_ptr->len; ioc->free_location += rdw_ptr->len; } @@ -736,7 +737,7 @@ static int write_flush(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) if (0 != rc) { - diag->e_msg_len = sprintf(diag->e_msg, "Failed to write record rc was: %d", rc); + ZDIAG_SET_MSG(diag, "Failed to write record rc was: %d", rc); diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; diag->service_rc = rc; return RTNCD_FAILURE; @@ -763,7 +764,7 @@ static int bldl_member(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc, BLDL_PL *PTR32 bld { diag->service_rc = rc; strcpy(diag->service_name, "BLDL"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to BLDL ddname: %8.8s data set: %44.44s rc was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rc); + ZDIAG_SET_MSG(diag, "Failed to BLDL ddname: %8.8s data set: %44.44s rc was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rc); diag->detail_rc = ZDS_RTNCD_BLDL_ERROR; } return rc; @@ -818,7 +819,7 @@ static int update_ispf_statistics(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) rc = zutm1gur(user); if (0 != rc) { - diag->e_msg_len = sprintf(diag->e_msg, "Failed to get userid rc was: %d", rc); + ZDIAG_SET_MSG(diag, "Failed to get userid rc was: %d", rc); diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; diag->service_rc = rc; return RTNCD_FAILURE; @@ -868,7 +869,7 @@ static int update_ispf_statistics(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) rc = zutm1gur(user); if (0 != rc) { - diag->e_msg_len = sprintf(diag->e_msg, "Failed to get userid rc was: %d", rc); + ZDIAG_SET_MSG(diag, "Failed to get userid rc was: %d", rc); diag->detail_rc = ZDS_RTNCD_SERVICE_FAILURE; diag->service_rc = rc; return RTNCD_FAILURE; @@ -922,7 +923,7 @@ static int stow_data_set(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) { diag->service_rc = rc; strcpy(diag->service_name, "STOW"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to STOW ISPF statistics: %8.8s data set: %44.44s rsn was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rsn); + ZDIAG_SET_MSG(diag, "Failed to STOW ISPF statistics: %8.8s data set: %44.44s rsn was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rsn); diag->detail_rc = ZDS_RTNCD_STOW_ERROR; } } @@ -946,7 +947,7 @@ static int close_data_set(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) { diag->service_rc = rc; strcpy(diag->service_name, "CLOSE"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to close ddname: %8.8s data set: %44.44s rc was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rc); + ZDIAG_SET_MSG(diag, "Failed to close ddname: %8.8s data set: %44.44s rc was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rc); diag->detail_rc = ZDS_RTNCD_CLOSE_ERROR; } } @@ -969,7 +970,7 @@ static int deq_reserve_data_set(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) { diag->service_rc = rc; strcpy(diag->service_name, "DEQ RESERVE"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to DEQ RESERVE ddname: %8.8s data set: %44.44s rc was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rc); + ZDIAG_SET_MSG(diag, "Failed to DEQ RESERVE ddname: %8.8s data set: %44.44s rc was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rc); diag->detail_rc = ZDS_RTNCD_DEQ_RESERVE_ERROR; } return rc; @@ -995,7 +996,7 @@ static int deq_data_set(ZDIAG *PTR32 diag, IO_CTRL *PTR32 ioc) { diag->service_rc = rc; strcpy(diag->service_name, "DEQ"); - diag->e_msg_len = sprintf(diag->e_msg, "Failed to DEQ ddname: %8.8s data set: %44.44s rc was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rc); + ZDIAG_SET_MSG(diag, "Failed to DEQ ddname: %8.8s data set: %44.44s rc was: %d", ioc->ddname, ioc->jfcb.jfcbdsnm, rc); diag->detail_rc = ZDS_RTNCD_DEQ_ERROR; } } diff --git a/native/c/zam24.s b/native/c/zam24.s index 6c8f28f32..498e9df95 100644 --- a/native/c/zam24.s +++ b/native/c/zam24.s @@ -24,7 +24,6 @@ ENTRY24 DS 0H OILH R15,X'8000' Set AMODE 31 bit for BASSM LA R1,WORK -> IO_CTRL "work" field BASSM 0,R15 Call ZAMDEXIT in AMODE 31 - BR R14 Return to system * CONSTANT DS 0D LTORG , diff --git a/native/c/zcn.cpp b/native/c/zcn.cpp index 4a5a126a7..26940c6fb 100644 --- a/native/c/zcn.cpp +++ b/native/c/zcn.cpp @@ -26,7 +26,7 @@ int zcn_activate(ZCN *zcn, const std::string &console_name) int rc = 0; zcn->diag.detail_rc = 0; - strcpy(zcn->eye, ZCN_EYE); + memcpy(zcn->eye, ZCN_EYE, sizeof(zcn->eye)); zut_uppercase_pad_truncate(zcn->console_name, console_name, sizeof(zcn->console_name)); @@ -56,7 +56,7 @@ int zcn_put(ZCN *zcn, const std::string &command) char *command31 = (char *)__malloc31(command.length() + 1); if (command31 == nullptr) { - zcn->diag.e_msg_len = sprintf(zcn->diag.e_msg, "Failed to allocate 31-bit memory for command: %s", command.c_str()); + ZDIAG_SET_MSG(&zcn->diag, "Failed to allocate 31-bit memory for command: %s", command.c_str()); return RTNCD_FAILURE; } memset(command31, 0x00, command.length() + 1); @@ -86,7 +86,7 @@ int zcn_get(ZCN *zcn, std::string &response) char *resp31 = (char *)__malloc31(zcn->buffer_size); if (resp31 == nullptr) { - zcn->diag.e_msg_len = sprintf(zcn->diag.e_msg, "Failed to allocate 31-bit memory for response"); + ZDIAG_SET_MSG(&zcn->diag, "Failed to allocate 31-bit memory for response"); return RTNCD_FAILURE; } memset(resp31, 0x00, zcn->buffer_size); diff --git a/native/c/zcnm.c b/native/c/zcnm.c index 60ecfa22f..1510fc634 100644 --- a/native/c/zcnm.c +++ b/native/c/zcnm.c @@ -27,7 +27,7 @@ int ZCNACT(ZCN *zcn) if (0 != rc) { strcpy(zcn->diag.service_name, "TESTAUTH"); - zcn->diag.e_msg_len = sprintf(zcn->diag.e_msg, "Not authorized - %d", rc); + ZDIAG_SET_MSG(&zcn->diag, "Not authorized - %d", rc); zcn->diag.detail_rc = ZCN_RTNCD_NOT_AUTH; return RTNCD_FAILURE; } @@ -42,7 +42,7 @@ int ZCNACT(ZCN *zcn) memcpy(zcn, &zcn31, sizeof(ZCN)); if (0 != rc) { - zcn->diag.e_msg_len = sprintf(zcn->diag.e_msg, "Error activating console, service: %s, rc: %d, service_rc: %d, service_rsn: %d", zcn->diag.service_name, rc, zcn->diag.service_rc, zcn->diag.service_rsn); + ZDIAG_SET_MSG(&zcn->diag, "Error activating console, service: %.16s, rc: %d, service_rc: %d, service_rsn: %d", zcn->diag.service_name, rc, zcn->diag.service_rc, zcn->diag.service_rsn); rc = RTNCD_FAILURE; } } @@ -67,7 +67,7 @@ int ZCNPUT(ZCN *zcn, const char *command) if (0 != rc) { strcpy(zcn->diag.service_name, "TESTAUTH"); - zcn->diag.e_msg_len = sprintf(zcn->diag.e_msg, "Not authorized - %d", rc); + ZDIAG_SET_MSG(&zcn->diag, "Not authorized - %d", rc); zcn->diag.detail_rc = ZCN_RTNCD_NOT_AUTH; return RTNCD_FAILURE; } @@ -79,7 +79,7 @@ int ZCNPUT(ZCN *zcn, const char *command) if (0 != rc) { - zcn->diag.e_msg_len = sprintf(zcn->diag.e_msg, "Error writting data to console, service: %s, rc: %d, service_rc: %d, service_rsn: %d", zcn->diag.service_name, rc, zcn->diag.service_rc, zcn->diag.service_rsn); + ZDIAG_SET_MSG(&zcn->diag, "Error writting data to console, service: %.16s, rc: %d, service_rc: %d, service_rsn: %d", zcn->diag.service_name, rc, zcn->diag.service_rc, zcn->diag.service_rsn); return RTNCD_FAILURE; } @@ -120,7 +120,7 @@ int ZCNGET(ZCN *zcn, char *response) if (0 != rc) { strcpy(zcn->diag.service_name, "TESTAUTH"); - zcn->diag.e_msg_len = sprintf(zcn->diag.e_msg, "Not authorized - %d", rc); + ZDIAG_SET_MSG(&zcn->diag, "Not authorized - %d", rc); zcn->diag.detail_rc = ZCN_RTNCD_NOT_AUTH; return RTNCD_FAILURE; } @@ -140,7 +140,7 @@ int ZCNGET(ZCN *zcn, char *response) if (0 != rc) { - zcn->diag.e_msg_len = sprintf(zcn->diag.e_msg, "Error getting data from console, service: %s, rc: %d, service_rc: %d, service_rsn: %d", zcn->diag.service_name, rc, zcn->diag.service_rc, zcn->diag.service_rsn); + ZDIAG_SET_MSG(&zcn->diag, "Error getting data from console, service: %.16s, rc: %d, service_rc: %d, service_rsn: %d", zcn->diag.service_name, rc, zcn->diag.service_rc, zcn->diag.service_rsn); return RTNCD_FAILURE; } @@ -157,7 +157,7 @@ int ZCNDACT(ZCN *zcn) if (0 != rc) { strcpy(zcn->diag.service_name, "TESTAUTH"); - zcn->diag.e_msg_len = sprintf(zcn->diag.e_msg, "Not authorized - %d", rc); + ZDIAG_SET_MSG(&zcn->diag, "Not authorized - %d", rc); zcn->diag.detail_rc = ZCN_RTNCD_NOT_AUTH; return RTNCD_FAILURE; } @@ -169,7 +169,7 @@ int ZCNDACT(ZCN *zcn) if (0 != rc) { - zcn->diag.e_msg_len = sprintf(zcn->diag.e_msg, "Error deactivating console, service: %s, rc: %d, service_rc: %d, service_rsn: %d", zcn->diag.service_name, rc, zcn->diag.service_rc, zcn->diag.service_rsn); + ZDIAG_SET_MSG(&zcn->diag, "Error deactivating console, service: %.16s, rc: %d, service_rc: %d, service_rsn: %d", zcn->diag.service_name, rc, zcn->diag.service_rc, zcn->diag.service_rsn); return RTNCD_FAILURE; } diff --git a/native/c/zcnm31.c b/native/c/zcnm31.c index 4295ed8dc..fb10a5082 100644 --- a/native/c/zcnm31.c +++ b/native/c/zcnm31.c @@ -119,6 +119,11 @@ MGCRE_MODEL(mgcre_model); #define MGCRE(id, message, cart, authcmdx, plist) #endif +// MGCETXT Command text - Table 2 "MGCRE mapping", structure "MGCETEXT" https://www.ibm.com/docs/en/zos/3.2.0?topic=rqe-mgcre-information +#ifndef MGCRTEXT +#define MGCRTEXT 126 +#endif + // NOTE(Kelosky): this piece is permitted in AMODE64 - for consistency, it remains here int zcnm1put(ZCN *zcn, const char *command) { @@ -131,16 +136,17 @@ int zcnm1put(ZCN *zcn, const char *command) MGCRE_MODEL(dsa_mgcre_model); dsa_mgcre_model = mgcre_model; - struct + struct MGCETEXT { short commandLen; - char command[256]; + char command[MGCRTEXT]; } commandBuffer = {0}; unsigned short authcmdx = 0x8000; // 1000000000000000 - Master Authority - https://www.ibm.com/docs/en/zos/3.1.0?topic=commands-mgcre-execute-form unsigned short *authcmdxp = &authcmdx; - commandBuffer.commandLen = sprintf(commandBuffer.command, "%s", command); + /* Use precision specifier %.*s as snprintf is unavailable in Metal C */ + commandBuffer.commandLen = sprintf(commandBuffer.command, "%.*s", (int)(sizeof(commandBuffer.command) - 1), command); char cart[8] = "ZOWECART"; strcpy(zcn->diag.service_name, "MGCRE"); @@ -287,6 +293,11 @@ static void extract_control_info(unsigned int alet, unsigned char *offset, ZCN * char *FAR reply_id = __set_far_ALET_offset(0, zcn->reply_id); zcn->reply_id_len = mdbscp->mdbcrpyl; + if (zcn->reply_id_len > 8) + { + // Truncate reply ID length to 8 characters (max length of reply ID) + zcn->reply_id_len = 8; + } __far_memcpy(reply_id, mdbscp->mdbcrpyi, zcn->reply_id_len); } @@ -298,6 +309,12 @@ static int extract_text(unsigned int alet, unsigned char *offset, int len, char char b[256] = {0}; char *FAR bp = __set_far_ALET_offset(0, b); + if (len > 256) + { + // Truncate text length to 256 characters (max length of text buffer) + len = 256; + } + __far_memcpy(bp, text, len); memcpy(resp, b, len); diff --git a/native/c/zdbg.h b/native/c/zdbg.h index 24bc38b08..f69c36001 100644 --- a/native/c/zdbg.h +++ b/native/c/zdbg.h @@ -34,7 +34,8 @@ static void zut_dump_storage_common(const char *title, const void *data, int siz { int len = 0; char buf[1024] = {0}; - len += sprintf(buf + len, "--- Dumping storage for '%s' at x'%016llx' ---", title, (unsigned long long)data); + /* Safe title length limit (100) to avoid buf overflow */ + len += sprintf(buf + len, "--- Dumping storage for '%.100s' at x'%016llx' ---", title, (unsigned long long)data); if (new_line) { len += sprintf(buf + len, "\n"); diff --git a/native/c/zds.cpp b/native/c/zds.cpp index 9b03087ad..7b050ce15 100644 --- a/native/c/zds.cpp +++ b/native/c/zds.cpp @@ -290,12 +290,12 @@ static int copy_partitioned(ZDS *zds, const ZDSTypeInfo &sourceInfo, const ZDSTy { if (targetIsPds) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, + ZDIAG_SET_MSG(&zds->diag, "Target data set '%s' exists. Use --replace (-r) flag to replace like-named members or --overwrite to replace the entire partitioned data set", targetInfo.base_dsn.c_str()); } else { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, + ZDIAG_SET_MSG(&zds->diag, "Target member '%s' exists. Use --replace (-r) flag to replace the member's contents", targetInfo.member_name.c_str()); } return RTNCD_FAILURE; @@ -449,20 +449,20 @@ int zds_copy_dsn(ZDS *zds, const std::string &dsn1, const std::string &dsn2, ZDS if (!zds_dataset_exists(info1.base_dsn)) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Source data set '%s' not found", info1.base_dsn.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Source data set '%s' not found", info1.base_dsn.c_str()); return RTNCD_FAILURE; } if (!info1.member_name.empty() && !zds_member_exists(info1.base_dsn, info1.member_name)) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Source member '%s' not found", info1.member_name.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Source member '%s' not found", info1.member_name.c_str()); return RTNCD_FAILURE; } // PDS -> Member is not supported if (info1.type == ZDS_TYPE_PDS && target_type == ZDS_TYPE_MEMBER) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, + ZDIAG_SET_MSG(&zds->diag, "Cannot copy a partitioned data set to a member. " "Target must be a partitioned data set."); return RTNCD_FAILURE; @@ -471,7 +471,7 @@ int zds_copy_dsn(ZDS *zds, const std::string &dsn1, const std::string &dsn2, ZDS // Member -> PS is not supported if (info1.type == ZDS_TYPE_MEMBER && target_type == ZDS_TYPE_PS) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, + ZDIAG_SET_MSG(&zds->diag, "Cannot copy partitioned data set member to a sequential data set. Target must be a data set member"); return RTNCD_FAILURE; } @@ -479,7 +479,7 @@ int zds_copy_dsn(ZDS *zds, const std::string &dsn1, const std::string &dsn2, ZDS // PS -> Member is not supported if (info1.type == ZDS_TYPE_PS && target_type == ZDS_TYPE_MEMBER) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, + ZDIAG_SET_MSG(&zds->diag, "Cannot copy sequential data set to a data set member. " "Target must be a sequential data set."); return RTNCD_FAILURE; @@ -488,7 +488,7 @@ int zds_copy_dsn(ZDS *zds, const std::string &dsn1, const std::string &dsn2, ZDS // PDS -> PS is not supported if (info1.type == ZDS_TYPE_PDS && target_type == ZDS_TYPE_PS) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, + ZDIAG_SET_MSG(&zds->diag, "Cannot copy a partitioned data set to a sequential data set. " "Target must be a partitioned data set."); return RTNCD_FAILURE; @@ -513,7 +513,7 @@ int zds_copy_dsn(ZDS *zds, const std::string &dsn1, const std::string &dsn2, ZDS rc = zut_bpxwdyn(create, &code, create_resp); if (rc != RTNCD_SUCCESS) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to create target data set '%s' using LIKE('%s'): %s", + ZDIAG_SET_MSG(&zds->diag, "Failed to create target data set '%s' using LIKE('%s'): %s", dsn2.c_str(), dsn1.c_str(), create_resp.c_str()); return RTNCD_FAILURE; } @@ -530,7 +530,7 @@ int zds_copy_dsn(ZDS *zds, const std::string &dsn1, const std::string &dsn2, ZDS } else { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Copy between these types is not supported."); + ZDIAG_SET_MSG(&zds->diag, "Copy between these types is not supported."); return RTNCD_FAILURE; } @@ -723,7 +723,7 @@ static int zds_validate_write_opts(const ZDSWriteOpts &opts, const char *caller) } if (opts.dsname.empty() && opts.ddname.empty()) { - opts.zds->diag.e_msg_len = sprintf(opts.zds->diag.e_msg, "Either a dsname or ddname must be provided"); + ZDIAG_SET_MSG(&opts.zds->diag, "Either a dsname or ddname must be provided"); return RTNCD_FAILURE; } return RTNCD_SUCCESS; @@ -745,7 +745,7 @@ static int zds_validate_read_opts(const ZDSReadOpts &opts, const char *caller) } if (opts.dsname.empty() && opts.ddname.empty()) { - opts.zds->diag.e_msg_len = sprintf(opts.zds->diag.e_msg, "Either a dsname or ddname must be provided"); + ZDIAG_SET_MSG(&opts.zds->diag, "Either a dsname or ddname must be provided"); return RTNCD_FAILURE; } return RTNCD_SUCCESS; @@ -785,7 +785,7 @@ int zds_read(const ZDSReadOpts &opts, std::string &response) FileGuard fp(dsname.c_str(), fopen_flags.c_str()); if (!fp) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Could not open handle to %s '%s'", is_dd ? "DD" : "data set", dsname.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Could not open handle to %s '%s'", is_dd ? "DD" : "data set", dsname.c_str()); return RTNCD_FAILURE; } @@ -851,7 +851,7 @@ int zds_read(const ZDSReadOpts &opts, std::string &response) } catch (std::exception &e) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to convert input data from %s to %s", source_encoding.c_str(), zds->encoding_opts.codepage); + ZDIAG_SET_MSG(&zds->diag, "Failed to convert input data from %s to %s", source_encoding.c_str(), zds->encoding_opts.codepage); return RTNCD_FAILURE; } if (!temp.empty()) @@ -1025,7 +1025,7 @@ static int handle_truncation_result(ZDS *zds, int write_rc, const TruncationTrac if (truncation.count > 0) { const auto warning_msg = truncation.get_warning_message(); - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "%s", warning_msg.c_str()); + ZDIAG_SET_MSG(&zds->diag, "%s", warning_msg.c_str()); zds->diag.detail_rc = ZDS_RSNCD_TRUNCATION_WARNING; return RTNCD_WARNING; } @@ -1051,7 +1051,7 @@ static int validate_iconv_setup(const EncodingSetup &setup, const IconvGuard &ic if (!iconv_guard.is_valid()) { - diag.e_msg_len = sprintf(diag.e_msg, "Cannot open converter from %s to %s", + ZDIAG_SET_MSG(&diag, "Cannot open converter from %s to %s", setup.source_encoding.c_str(), setup.codepage.c_str()); return RTNCD_FAILURE; } @@ -1087,7 +1087,7 @@ static int encode_chunk_if_needed(const char *&chunk, int &chunk_len, std::vecto } catch (std::exception &e) { - diag.e_msg_len = sprintf(diag.e_msg, "Failed to convert input data from %s to %s", + ZDIAG_SET_MSG(&diag, "Failed to convert input data from %s to %s", setup.source_encoding.c_str(), setup.codepage.c_str()); return RTNCD_FAILURE; } @@ -1121,7 +1121,7 @@ static int flush_encoding_state(const EncodingSetup &setup, IconvGuard &iconv_gu } catch (std::exception &e) { - diag.e_msg_len = sprintf(diag.e_msg, "Failed to flush encoding state"); + ZDIAG_SET_MSG(&diag, "Failed to flush encoding state"); return RTNCD_FAILURE; } } @@ -1150,7 +1150,7 @@ static int encode_line_if_needed(std::string &line, const EncodingSetup &setup, } catch (std::exception &e) { - diag.e_msg_len = sprintf(diag.e_msg, "Failed to convert input data from %s to %s", + ZDIAG_SET_MSG(&diag, "Failed to convert input data from %s to %s", setup.source_encoding.c_str(), setup.codepage.c_str()); return RTNCD_FAILURE; } @@ -1401,7 +1401,7 @@ static int zds_write_sequential(ZDS *zds, const std::string &dsn, const std::str FileGuard fp(dsname.c_str(), fopen_flags.c_str()); if (!fp) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Could not open dsn '%s'", dsn.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Could not open dsn '%s'", dsn.c_str()); return RTNCD_FAILURE; } @@ -1417,7 +1417,7 @@ static int zds_write_sequential(ZDS *zds, const std::string &dsn, const std::str } catch (std::exception &e) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to convert input data from %s to %s", encoding.source_encoding.c_str(), encoding.codepage.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Failed to convert input data from %s to %s", encoding.source_encoding.c_str(), encoding.codepage.c_str()); return RTNCD_FAILURE; } } @@ -1432,7 +1432,7 @@ static int zds_write_sequential(ZDS *zds, const std::string &dsn, const std::str size_t bytes_written = fwrite(temp.c_str(), 1u, temp.length(), fp); if (bytes_written != temp.length()) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to write all contents to '%s' (possibly out of space)", dsname.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Failed to write all contents to '%s' (possibly out of space)", dsname.c_str()); return RTNCD_FAILURE; } } @@ -1657,7 +1657,7 @@ int zds_validate_etag(ZDS *zds, const std::string &dsn, bool has_encoding) char truncated_detail[128]; strncpy(truncated_detail, read_zds.diag.e_msg, sizeof(truncated_detail) - 1); truncated_detail[sizeof(truncated_detail) - 1] = '\0'; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, + ZDIAG_SET_MSG(&zds->diag, "Failed to read contents of data set for e-tag comparison: %s", truncated_detail); return RTNCD_FAILURE; } @@ -1674,7 +1674,7 @@ int zds_validate_etag(ZDS *zds, const std::string &dsn, bool has_encoding) ss << std::hex << new_etag << std::dec; const auto error_msg = ss.str(); - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "%s", error_msg.c_str()); + ZDIAG_SET_MSG(&zds->diag, "%s", error_msg.c_str()); return RTNCD_FAILURE; } @@ -1693,7 +1693,7 @@ static int validate_dataset_exists(const std::string &dsn, ZDIAG &diag) { if (!zds_dataset_exists(dsn)) { - diag.e_msg_len = sprintf(diag.e_msg, "Could not access '%s'", dsn.c_str()); + ZDIAG_SET_MSG(&diag, "Could not access '%s'", dsn.c_str()); return RTNCD_FAILURE; } return RTNCD_SUCCESS; @@ -1712,7 +1712,7 @@ static int validate_write_recfm(const DscbAttributes &attrs, bool is_member, ZDI { if (zds_write_recfm_unsupported(attrs.recfm, !is_member)) { - diag.e_msg_len = sprintf(diag.e_msg, "Writing to RECFM=%s data sets is not supported", attrs.recfm.c_str()); + ZDIAG_SET_MSG(&diag, "Writing to RECFM=%s data sets is not supported", attrs.recfm.c_str()); diag.detail_rc = ZDS_RTNCD_UNSUPPORTED_RECFM; return RTNCD_FAILURE; } @@ -1827,7 +1827,7 @@ int zds_write_streamed(const ZDSWriteOpts &opts, const std::string &pipe, size_t if (content_len == nullptr) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "content_len must be a valid size_t pointer"); + ZDIAG_SET_MSG(&zds->diag, "content_len must be a valid size_t pointer"); return RTNCD_FAILURE; } @@ -1910,7 +1910,7 @@ int zds_open_output_bpam(ZDS *zds, const std::string &dsname, IO_CTRL *&ioc) if (0 != rc) { strcpy(zds->diag.service_name, "BPXWDYN"); - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to allocate with code '%08X' on data set '%s': %s", code, dsname.c_str(), resp.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Failed to allocate with code '%08X' on data set '%s': %s", code, dsname.c_str(), resp.c_str()); zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; zds->diag.service_rc = code; return RTNCD_FAILURE; @@ -1949,7 +1949,7 @@ int zds_write_output_bpam(ZDS *zds, IO_CTRL *ioc, std::string &data, char asa_ch { if (0 == zds->diag.e_msg_len) // only set error if no error message was already set { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to write output to BPAM: %s... (%d bytes)", data.substr(0, 20).c_str(), length); + ZDIAG_SET_MSG(&zds->diag, "Failed to write output to BPAM: %s... (%d bytes)", data.substr(0, 20).c_str(), length); return RTNCD_FAILURE; } } @@ -1964,7 +1964,7 @@ int zds_close_output_bpam(ZDS *zds, IO_CTRL *ioc) if (ioc == nullptr) { zds->diag.detail_rc = RTNCD_WARNING; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "IO_CTRL is NULL"); + ZDIAG_SET_MSG(&zds->diag, "IO_CTRL is NULL"); rc = RTNCD_WARNING; } else @@ -1977,7 +1977,7 @@ int zds_close_output_bpam(ZDS *zds, IO_CTRL *ioc) if (0 == zds->diag.e_msg_len) // only set error if no error message was already set { zds->diag.detail_rc = RTNCD_WARNING; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Data set was not dynamically allocated"); + ZDIAG_SET_MSG(&zds->diag, "Data set was not dynamically allocated"); } } else @@ -1990,7 +1990,7 @@ int zds_close_output_bpam(ZDS *zds, IO_CTRL *ioc) { zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; zds->diag.service_rc = code; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to free with code '%08X' on data set '%s': %s", code, zds->ddname, resp.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Failed to free with code '%08X' on DD '%.*s': %s", code, (int)sizeof(zds->ddname), zds->ddname, resp.c_str()); rc = RTNCD_FAILURE; } } @@ -2191,7 +2191,7 @@ int zds_delete_dsn(ZDS *zds, std::string dsn) { strcpy(zds->diag.service_name, "remove"); zds->diag.service_rc = rc; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Could not delete data set '%s', rc: '%d'", dsn.c_str(), rc); + ZDIAG_SET_MSG(&zds->diag, "Could not delete data set '%s', rc: '%d'", dsn.c_str(), rc); zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; return RTNCD_FAILURE; } @@ -2204,22 +2204,22 @@ int zds_rename_dsn(ZDS *zds, std::string dsn_before, std::string dsn_after) int rc = 0; if (dsn_before.empty() || dsn_after.empty()) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Data set names must be valid"); + ZDIAG_SET_MSG(&zds->diag, "Data set names must be valid"); return RTNCD_FAILURE; } if (dsn_after.length() > 44) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Target data set name exceeds max character length of 44"); + ZDIAG_SET_MSG(&zds->diag, "Target data set name exceeds max character length of 44"); return RTNCD_FAILURE; } if (!zds_dataset_exists(dsn_before)) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Source data set does not exist '%s'", dsn_before.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Source data set does not exist '%s'", dsn_before.c_str()); return RTNCD_FAILURE; } if (zds_dataset_exists(dsn_after)) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Target data set name already exists '%s'", dsn_after.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Target data set name already exists '%s'", dsn_after.c_str()); return RTNCD_FAILURE; } @@ -2234,7 +2234,7 @@ int zds_rename_dsn(ZDS *zds, std::string dsn_before, std::string dsn_after) int err = errno; strcpy(zds->diag.service_name, "rename"); zds->diag.service_rc = rc; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Could not rename data set '%s', errno: '%d'", dsn_before.c_str(), err); + ZDIAG_SET_MSG(&zds->diag, "Could not rename data set '%s', errno: '%d'", dsn_before.c_str(), err); zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; return RTNCD_FAILURE; } @@ -2247,32 +2247,32 @@ int zds_rename_members(ZDS *zds, const std::string &dsname, const std::string &m int rc = 0; if (dsname.empty()) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Data set name must be valid"); + ZDIAG_SET_MSG(&zds->diag, "Data set name must be valid"); return RTNCD_FAILURE; } if (member_before.empty() || member_after.empty()) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Member name cannot be empty"); + ZDIAG_SET_MSG(&zds->diag, "Member name cannot be empty"); return RTNCD_FAILURE; } if (!zds_dataset_exists(dsname)) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Data set does not exist"); + ZDIAG_SET_MSG(&zds->diag, "Data set does not exist"); return RTNCD_FAILURE; } if (!zds_member_exists(dsname, member_before)) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Source member does not exist"); + ZDIAG_SET_MSG(&zds->diag, "Source member does not exist"); return RTNCD_FAILURE; } if (zds_member_exists(dsname, member_after)) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Target member already exists"); + ZDIAG_SET_MSG(&zds->diag, "Target member already exists"); return RTNCD_FAILURE; } if (!zds_is_valid_member_name(member_after) || !zds_is_valid_member_name(member_before)) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Member name must start with A-Z,#,@,$ and contain only A-Z,0-9,#,@,$ (max 8 chars)"); + ZDIAG_SET_MSG(&zds->diag, "Member name must start with A-Z,#,@,$ and contain only A-Z,0-9,#,@,$ (max 8 chars)"); return RTNCD_FAILURE; } @@ -2286,7 +2286,7 @@ int zds_rename_members(ZDS *zds, const std::string &dsname, const std::string &m int err = errno; strcpy(zds->diag.service_name, "rename_members"); zds->diag.service_rc = rc; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Could not rename member '%s', errno: '%d'", source_member.c_str(), err); + ZDIAG_SET_MSG(&zds->diag, "Could not rename member '%s', errno: '%d'", source_member.c_str(), err); zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; return RTNCD_FAILURE; } @@ -3292,7 +3292,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset if (zds->buffer_size < min_buffer_size) { zds->diag.detail_rc = ZDS_RTNCD_INSUFFICIENT_BUFFER; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Minimum buffer size required is %d but %d was provided", min_buffer_size, zds->buffer_size); + ZDIAG_SET_MSG(&zds->diag, "Minimum buffer size required is %d but %d was provided", min_buffer_size, zds->buffer_size); return RTNCD_FAILURE; } @@ -3300,7 +3300,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset if (area == nullptr) { zds->diag.detail_rc = ZDS_RTNCD_INSUFFICIENT_BUFFER; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to allocate 31-bit buffer for workarea to list %s", dsn.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Failed to allocate 31-bit buffer for workarea to list %s", dsn.c_str()); return RTNCD_FAILURE; } memset(area, 0x00, zds->buffer_size); @@ -3345,7 +3345,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset strcpy(zds->diag.service_name, "ZDSCSI00"); zds->diag.service_rc = rc; zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "ZDSCSI00 failed with rc %d", rc); + ZDIAG_SET_MSG(&zds->diag, "ZDSCSI00 failed with rc %d", rc); return RTNCD_FAILURE; } @@ -3356,11 +3356,10 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset free(area); ZDSDEL(zds); zds->diag.detail_rc = ZDS_RTNCD_UNEXPECTED_ERROR; - zds->diag.e_msg_len = - sprintf(zds->diag.e_msg, - "Unexpected work area field response preset len %d and " - "return len %d are not equal", - number_fields, number_of_fields); + ZDIAG_SET_MSG(&zds->diag, + "Unexpected work area field response preset len %d and " + "return len %d are not equal", + number_fields, number_of_fields); return RTNCD_FAILURE; } @@ -3370,7 +3369,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset ZDSDEL(zds); zds->diag.detail_rc = ZDS_RTNCD_PARSING_ERROR; zds->diag.service_rc = ZDS_RTNCD_CATALOG_ERROR; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Unexpected catalog flag '%x' ", csi_work_area->catalog.flag); + ZDIAG_SET_MSG(&zds->diag, "Unexpected catalog flag '%x' ", csi_work_area->catalog.flag); return RTNCD_FAILURE; } @@ -3380,7 +3379,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset ZDSDEL(zds); zds->diag.detail_rc = ZDS_RTNCD_PARSING_ERROR; zds->diag.service_rc = ZDS_RTNCD_CATALOG_ERROR; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Unexpected catalog flag '%x' ", csi_work_area->catalog.flag); + ZDIAG_SET_MSG(&zds->diag, "Unexpected catalog flag '%x' ", csi_work_area->catalog.flag); return RTNCD_FAILURE; } @@ -3390,7 +3389,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset ZDSDEL(zds); zds->diag.detail_rc = ZDS_RSNCD_NOT_FOUND; zds->diag.service_rc = ZDS_RTNCD_CATALOG_ERROR; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Not found in catalog, flag '%x' ", csi_work_area->catalog.flag); + ZDIAG_SET_MSG(&zds->diag, "Not found in catalog, flag '%x' ", csi_work_area->catalog.flag); return RTNCD_WARNING; } @@ -3400,7 +3399,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset ZDSDEL(zds); zds->diag.detail_rc = ZDS_RTNCD_PARSING_ERROR; zds->diag.service_rc = ZDS_RTNCD_CATALOG_ERROR; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Unexpected type '%x' ", csi_work_area->catalog.type); + ZDIAG_SET_MSG(&zds->diag, "Unexpected type '%x' ", csi_work_area->catalog.type); return RTNCD_FAILURE; } @@ -3424,7 +3423,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset ZDSDEL(zds); zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; zds->diag.service_rc = ZDS_RTNCD_ENTRY_ERROR; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Unexpected entry flag '%x' ", f->flag); + ZDIAG_SET_MSG(&zds->diag, "Unexpected entry flag '%x' ", f->flag); return RTNCD_FAILURE; } @@ -3434,7 +3433,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset ZDSDEL(zds); zds->diag.detail_rc = ZDS_RTNCD_NOT_FOUND; zds->diag.service_rc = ZDS_RTNCD_ENTRY_ERROR; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "No entry found '%x' ", f->type); + ZDIAG_SET_MSG(&zds->diag, "No entry found '%x' ", f->type); return RTNCD_FAILURE; } @@ -3454,7 +3453,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset ZDSDEL(zds); zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; zds->diag.service_rc = ZDS_RTNCD_UNSUPPORTED_ERROR; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Unsupported entry type '%x' ", f->type); + ZDIAG_SET_MSG(&zds->diag, "Unsupported entry type '%x' ", f->type); return RTNCD_FAILURE; } @@ -3535,7 +3534,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset ZDSDEL(zds); zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; zds->diag.service_rc = ZDS_RTNCD_UNSUPPORTED_ERROR; - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Unsupported entry type '%x' ", f->type); + ZDIAG_SET_MSG(&zds->diag, "Unsupported entry type '%x' ", f->type); return RTNCD_FAILURE; }; @@ -3550,7 +3549,7 @@ int zds_list_data_sets(ZDS *zds, std::string dsn, std::vector &dataset { free(area); ZDSDEL(zds); - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Reached maximum returned records requested %d", zds->max_entries); + ZDIAG_SET_MSG(&zds->diag, "Reached maximum returned records requested %d", zds->max_entries); zds->diag.detail_rc = ZDS_RSNCD_MAXED_ENTRIES_REACHED; return RTNCD_WARNING; } @@ -3589,7 +3588,7 @@ int zds_read_streamed(const ZDSReadOpts &opts, const std::string &pipe, size_t * if (content_len == nullptr) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "content_len must be a valid size_t pointer"); + ZDIAG_SET_MSG(&zds->diag, "content_len must be a valid size_t pointer"); return RTNCD_FAILURE; } @@ -3618,7 +3617,7 @@ int zds_read_streamed(const ZDSReadOpts &opts, const std::string &pipe, size_t * FileGuard fin(dsname.c_str(), fopen_flags.c_str()); if (!fin) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Could not open handle to %s '%s'", is_dd ? "DD" : "data set", dsname.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Could not open handle to %s '%s'", is_dd ? "DD" : "data set", dsname.c_str()); return RTNCD_FAILURE; } @@ -3626,7 +3625,7 @@ int zds_read_streamed(const ZDSReadOpts &opts, const std::string &pipe, size_t * FileGuard fout(fifo_fd, "w"); if (!fout) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Could not open output pipe '%s'", pipe.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Could not open output pipe '%s'", pipe.c_str()); close(fifo_fd); return RTNCD_FAILURE; } @@ -3642,7 +3641,7 @@ int zds_read_streamed(const ZDSReadOpts &opts, const std::string &pipe, size_t * IconvGuard iconv_guard(has_encoding ? source_encoding.c_str() : nullptr, has_encoding ? codepage.c_str() : nullptr); if (has_encoding && !iconv_guard.is_valid()) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Cannot open converter from %s to %s", codepage.c_str(), source_encoding.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Cannot open converter from %s to %s", codepage.c_str(), source_encoding.c_str()); return RTNCD_FAILURE; } @@ -3687,7 +3686,7 @@ int zds_read_streamed(const ZDSReadOpts &opts, const std::string &pipe, size_t * } catch (std::exception &e) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to convert input data from %s to %s", codepage.c_str(), source_encoding.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Failed to convert input data from %s to %s", codepage.c_str(), source_encoding.c_str()); return RTNCD_FAILURE; } } @@ -3714,7 +3713,7 @@ int zds_read_streamed(const ZDSReadOpts &opts, const std::string &pipe, size_t * } catch (std::exception &e) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to convert input data from %s to %s", codepage.c_str(), source_encoding.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Failed to convert input data from %s to %s", codepage.c_str(), source_encoding.c_str()); return RTNCD_FAILURE; } } @@ -3746,7 +3745,7 @@ int zds_read_streamed(const ZDSReadOpts &opts, const std::string &pipe, size_t * } catch (std::exception &e) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to convert input data from %s to %s", codepage.c_str(), source_encoding.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Failed to convert input data from %s to %s", codepage.c_str(), source_encoding.c_str()); return RTNCD_FAILURE; } } @@ -3778,7 +3777,7 @@ int zds_read_streamed(const ZDSReadOpts &opts, const std::string &pipe, size_t * } catch (std::exception &e) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to flush encoding state"); + ZDIAG_SET_MSG(&zds->diag, "Failed to flush encoding state"); return RTNCD_FAILURE; } } @@ -3827,21 +3826,21 @@ static int zds_write_sequential_streamed(ZDS *zds, const std::string &dsn, const FileGuard fout(dsname.c_str(), fopen_flags.c_str()); if (!fout) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Could not open dsn '%s'", dsn.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Could not open dsn '%s'", dsn.c_str()); return RTNCD_FAILURE; } int fifo_fd = open(pipe.c_str(), O_RDONLY); if (fifo_fd == -1) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "open() failed on input pipe '%s', errno %d", pipe.c_str(), errno); + ZDIAG_SET_MSG(&zds->diag, "open() failed on input pipe '%s', errno %d", pipe.c_str(), errno); return RTNCD_FAILURE; } FileGuard fin(fifo_fd, "r"); if (!fin) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Could not open input pipe '%s'", pipe.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Could not open input pipe '%s'", pipe.c_str()); close(fifo_fd); return RTNCD_FAILURE; } @@ -3950,7 +3949,7 @@ static int zds_write_sequential_streamed(ZDS *zds, const std::string &dsn, const const int flush_rc = fflush(fout); if (write_failed || flush_rc != 0) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Failed to write to '%44.44s' (possibly out of space)", dsname.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Failed to write to '%44.44s' (possibly out of space)", dsname.c_str()); return RTNCD_FAILURE; } } @@ -3981,7 +3980,7 @@ static int zds_write_member_bpam_streamed(ZDS *zds, const std::string &dsn, cons int fifo_fd = open(pipe.c_str(), O_RDONLY); if (fifo_fd == -1) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "open() failed on input pipe '%s', errno %d", pipe.c_str(), errno); + ZDIAG_SET_MSG(&zds->diag, "open() failed on input pipe '%s', errno %d", pipe.c_str(), errno); zds_close_output_bpam(zds, ioc); return RTNCD_FAILURE; } @@ -3989,7 +3988,7 @@ static int zds_write_member_bpam_streamed(ZDS *zds, const std::string &dsn, cons FileGuard fin(fifo_fd, "r"); if (!fin) { - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Could not open input pipe '%s'", pipe.c_str()); + ZDIAG_SET_MSG(&zds->diag, "Could not open input pipe '%s'", pipe.c_str()); close(fifo_fd); zds_close_output_bpam(zds, ioc); return RTNCD_FAILURE; diff --git a/native/c/zdsm.c b/native/c/zdsm.c index 0303f0812..6737cef4b 100644 --- a/native/c/zdsm.c +++ b/native/c/zdsm.c @@ -60,7 +60,7 @@ int ZDSCSI00(ZDS *zds, CSIFIELD *selection, void *work_area) if (!zds->csi) { strcpy(zds->diag.service_name, "LOAD"); - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "Load failure for IGGCSI00"); + ZDIAG_SET_MSG(&zds->diag, "Load failure for IGGCSI00"); zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; return RTNCD_FAILURE; } @@ -71,7 +71,7 @@ int ZDSCSI00(ZDS *zds, CSIFIELD *selection, void *work_area) if (0 != rc) { strcpy(zds->diag.service_name, "IGGCSI00"); - zds->diag.e_msg_len = sprintf(zds->diag.e_msg, "IGGCSI00 rc was: '%d', rsn was: '%04x'", rc, rsn); + ZDIAG_SET_MSG(&zds->diag, "IGGCSI00 rc was: '%d', rsn was: '%04x'", rc, rsn); zds->diag.service_rc = rc; zds->diag.service_rsn = rsn; zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; @@ -118,13 +118,13 @@ int ZDSDSCB1(ZDS *zds, const char *dsn, const char *volser, DSCBFormat1 *dscb) params.number_dscbs = MAX_DSCBS; params.option_flags = OPTION_EADSCB; // Allow lookup of format-1 or format-8 DSCB - char dsname[44] = {0}; + char dsname[ZDS_MAX_DSNAME_LENGTH] = {0}; memset(dsname, ' ', sizeof(dsname)); - memcpy(dsname, dsn, strlen(dsn)); + memcpy(dsname, dsn, ZMIN(strlen(dsn), ZDS_MAX_DSNAME_LENGTH)); params.listname_addrx.dsname_ptr = dsname; - char volume[6] = {0}; + char volume[ZDS_MAX_VOLSER_LENGTH] = {0}; memset(volume, ' ', sizeof(volume)); - memcpy(volume, volser, strlen(volser)); + memcpy(volume, volser, ZMIN(strlen(volser), ZDS_MAX_VOLSER_LENGTH)); params.listname_addrx.volume_ptr = volume; params.listname_addrx.workarea_ptr = workarea; @@ -132,8 +132,7 @@ int ZDSDSCB1(ZDS *zds, const char *dsn, const char *volser, DSCBFormat1 *dscb) if (0 != rc) { strcpy(zds->diag.service_name, "OBTAIN"); - zds->diag.e_msg_len = - sprintf(zds->diag.e_msg, "OBTAIN SVC failed for %s on %s with rc=%d, workarea_ptr=%p", + ZDIAG_SET_MSG(&zds->diag, "OBTAIN SVC failed for %.44s on %.6s with rc=%d, workarea_ptr=%p", dsn, volser, rc, workarea); zds->diag.service_rc = rc; zds->diag.detail_rc = ZDS_RTNCD_SERVICE_FAILURE; @@ -158,8 +157,7 @@ int ZDSDSCB1(ZDS *zds, const char *dsn, const char *volser, DSCBFormat1 *dscb) } strcpy(zds->diag.service_name, "OBTAIN"); - zds->diag.e_msg_len = sprintf( - zds->diag.e_msg, "Could not find Format-1 or Format-8 DSCB, OBTAIN rc=%d, sizeof(dscb)=%d", rc, sizeof(IndexableDSCBFormat1)); + ZDIAG_SET_MSG(&zds->diag, "Could not find Format-1 or Format-8 DSCB, OBTAIN rc=%d, sizeof(dscb)=%d", rc, sizeof(IndexableDSCBFormat1)); zds->diag.detail_rc = ZDS_RTNCD_UNEXPECTED_ERROR; return RTNCD_FAILURE; } diff --git a/native/c/zdstype.h b/native/c/zdstype.h index 3e2f97b95..992a279e3 100644 --- a/native/c/zdstype.h +++ b/native/c/zdstype.h @@ -70,6 +70,9 @@ #define ZDS_DSORG_POU "POU" // Partitioned Unmovable #define ZDS_DSORG_DA "DA" // Direct Access +#define ZDS_MAX_DSNAME_LENGTH 44 +#define ZDS_MAX_VOLSER_LENGTH 6 + // DSNTYPE values #define ZDS_DSNTYPE_PDS "PDS" // Partitioned Data Set #define ZDS_DSNTYPE_LIBRARY "LIBRARY" // PDSE (Partitioned Data Set Extended) @@ -100,7 +103,8 @@ typedef struct int32_t len; // future use ZEncode encoding_opts; - char etag[8]; + char etag[9]; // 8 characters + null terminator + unsigned char _etag_ddname_pad[7]; char ddname[8]; int32_t max_entries; @@ -160,8 +164,8 @@ typedef struct DSCBFormat1 typedef struct IndexableDSCBFormat1 { - char ds1dsnam[44]; // Data set name (used as key) - DSCBFormat1 dscb1; // Contents of DSCB-1 + char ds1dsnam[ZDS_MAX_DSNAME_LENGTH]; // Data set name (used as key) + DSCBFormat1 dscb1; // Contents of DSCB-1 } IndexableDSCBFormat1; ZNP_PACK_OFF diff --git a/native/c/zjb.cpp b/native/c/zjb.cpp index 34eb4bd63..0b0a4516e 100644 --- a/native/c/zjb.cpp +++ b/native/c/zjb.cpp @@ -77,7 +77,7 @@ int zjb_get_job_dsn_by_key(ZJB *zjb, const std::string &jobid, int key, std::str if (0 != rc) { - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "Could not locate data set key '%d' on job '%s'", key, jobid.c_str()); + ZDIAG_SET_MSG(&zjb->diag, "Could not locate data set key '%d' on job '%s'", key, jobid.c_str()); zjb->diag.detail_rc = ZJB_RTNCD_JOB_DSN_KEY_NOT_FOUND; return RTNCD_WARNING; } @@ -112,7 +112,7 @@ int zjb_read_job_jcl(ZJB *zjb, const std::string &jobid, std::string &response) if (args.size() < MIN_SIZE) { - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "Unexpected data set name '%s' for jobid %s", list[0].dsn.c_str(), jobid.c_str()); + ZDIAG_SET_MSG(&zjb->diag, "Unexpected data set name '%s' for jobid %s", list[0].dsn.c_str(), jobid.c_str()); zjb->diag.detail_rc = ZJB_RTNCD_UNEXPECTED_ERROR; return RTNCD_FAILURE; } @@ -135,7 +135,7 @@ static int zjb_read_job_dynamic_allocation(ZJB *zjb, std::string jobdsn, std::st unsigned char *parms = (unsigned char *)__malloc31(total_size_needed); if (parms == nullptr) { - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "Failed to allocate 31-bit memory for job parms when reading %s", jobdsn.c_str()); + ZDIAG_SET_MSG(&zjb->diag, "Failed to allocate 31-bit memory for job parms when reading %s", jobdsn.c_str()); return RTNCD_FAILURE; } memset(parms, 0x00, total_size_needed); @@ -258,7 +258,7 @@ static int zjb_read_job_dynamic_allocation(ZJB *zjb, std::string jobdsn, std::st { strcpy(zjb->diag.service_name, "svc99"); zjb->diag.service_rc = rc; - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "Could not allocate job spool file '%s', rc: '%d' s99error: '%d' s99info: '%d'", jobdsn.c_str(), rc, s99parms->__S99ERROR, s99parms->__S99INFO); + ZDIAG_SET_MSG(&zjb->diag, "Could not allocate job spool file '%s', rc: '%d' s99error: '%d' s99info: '%d'", jobdsn.c_str(), rc, s99parms->__S99ERROR, s99parms->__S99INFO); zjb->diag.detail_rc = ZJB_RTNCD_SERVICE_FAILURE; free(parms); return RTNCD_FAILURE; @@ -290,7 +290,7 @@ static int zjb_free_job_dynamic_allocation(ZJB *zjb, std::string ddname) { strcpy(zjb->diag.service_name, "dynfree"); zjb->diag.service_rc = rc; - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "dynfree failed with %d", rc); + ZDIAG_SET_MSG(&zjb->diag, "dynfree failed with %d", rc); zjb->diag.detail_rc = ZJB_RTNCD_SERVICE_FAILURE; return RTNCD_FAILURE; } @@ -479,7 +479,7 @@ int zjb_submit(ZJB *zjb, const std::string &contents, std::string &jobid) { strcpy(zjb->diag.service_name, "dyninit"); zjb->diag.service_rc = rc; - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "dyninit failed with %d", rc); + ZDIAG_SET_MSG(&zjb->diag, "dyninit failed with %d", rc); zjb->diag.detail_rc = ZJB_RTNCD_SERVICE_FAILURE; return RTNCD_FAILURE; } @@ -499,7 +499,7 @@ int zjb_submit(ZJB *zjb, const std::string &contents, std::string &jobid) { strcpy(zjb->diag.service_name, "dynalloc"); zjb->diag.service_rc = rc; - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "dynalloc failed with %d", rc); + ZDIAG_SET_MSG(&zjb->diag, "dynalloc failed with %d", rc); zjb->diag.detail_rc = ZJB_RTNCD_SERVICE_FAILURE; return RTNCD_FAILURE; } @@ -515,7 +515,8 @@ int zjb_submit(ZJB *zjb, const std::string &contents, std::string &jobid) char cjobid[8 + 1] = {0}; // https://www.ibm.com/docs/en/zos/3.1.0?topic=iazsymbl-jes-system-symbols - rc = ZJBSYMB(zjb, "SYS_LASTJOBID", cjobid); + int jobid_size = sizeof(cjobid); + rc = ZJBSYMB(zjb, "SYS_LASTJOBID", cjobid, &jobid_size); if (0 != rc) { @@ -529,13 +530,14 @@ int zjb_submit(ZJB *zjb, const std::string &contents, std::string &jobid) { rc = dynfree(&ip); strcpy(zjb->diag.service_name, "intrdr"); - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "job submission failed"); + ZDIAG_SET_MSG(&zjb->diag, "job submission failed"); zjb->diag.detail_rc = ZJB_RTNCD_SUBMIT_ERROR; return RTNCD_FAILURE; } char ccorrelator[64 + 1] = {0}; - rc = ZJBSYMB(zjb, "SYS_CORR_LASTJOB", ccorrelator); + int correlator_size = sizeof(ccorrelator); + rc = ZJBSYMB(zjb, "SYS_CORR_LASTJOB", ccorrelator, &correlator_size); if (0 != rc) { @@ -550,7 +552,7 @@ int zjb_submit(ZJB *zjb, const std::string &contents, std::string &jobid) { strcpy(zjb->diag.service_name, "dynfree"); zjb->diag.service_rc = rc; - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "dynfree failed with %d", rc); + ZDIAG_SET_MSG(&zjb->diag, "dynfree failed with %d", rc); zjb->diag.detail_rc = ZJB_RTNCD_SERVICE_FAILURE; return RTNCD_FAILURE; } @@ -614,7 +616,7 @@ int zjb_list_dds(ZJB *zjb, const std::string &jobid, std::vector &jobDDs } ZUTMFR64(sysoutInfo); - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "no output DDs found for '%s'", jobid.c_str()); + ZDIAG_SET_MSG(&zjb->diag, "no output DDs found for '%s'", jobid.c_str()); zjb->diag.detail_rc = ZJB_RTNCD_VERBOSE_INFO_NOT_FOUND; return RTNCD_WARNING; } @@ -669,7 +671,7 @@ int zjb_view(ZJB *zjb, const std::string &jobid, ZJob &job) if (0 == entries) { - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "Could not locate job with id '%s'", jobid.c_str()); + ZDIAG_SET_MSG(&zjb->diag, "Could not locate job with id '%s'", jobid.c_str()); zjb->diag.detail_rc = ZJB_RTNCD_JOB_NOT_FOUND; return RTNCD_FAILURE; } diff --git a/native/c/zjbm.c b/native/c/zjbm.c index a4cd385d6..e35f0737a 100644 --- a/native/c/zjbm.c +++ b/native/c/zjbm.c @@ -87,7 +87,7 @@ static void init_stat(STAT *stat) #pragma prolog(ZJBSYMB, " ZWEPROLG NEWDSA=(YES,128) ") #pragma epilog(ZJBSYMB, " ZWEEPILG ") -int ZJBSYMB(ZJB *zjb, const char *symbol, char *value) +int ZJBSYMB(ZJB *zjb, const char *symbol, char *value, int *value_size) { int rc = 0; @@ -117,7 +117,7 @@ int ZJBSYMB(ZJB *zjb, const char *symbol, char *value) { // TODO(Kelosky): read jsymerad for errors strcpy(zjb->diag.service_name, "iazsymbl"); - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "IAZSYMBL RC was: '%d', JSYMRETN was: '%d', JSYMREAS: %d", rc, jsym.jsymretn, jsym.jsymreas); + ZDIAG_SET_MSG(&zjb->diag, "IAZSYMBL RC was: '%d', JSYMRETN was: '%d', JSYMREAS: %d", rc, jsym.jsymretn, jsym.jsymreas); zjb->diag.detail_rc = ZJB_RTNCD_SERVICE_FAILURE; return RTNCD_FAILURE; } @@ -125,9 +125,25 @@ int ZJBSYMB(ZJB *zjb, const char *symbol, char *value) p = (unsigned char *)&jsymbolOutput.jsymbolTable; // --> table JSYENTRY *jsymbolEntry = (JSYENTRY *)(p + jsymbolOutput.jsymbolTable.jsytent1); // --> first entry + // Validate buffer size to prevent overflow + if (jsymbolEntry->jsyevals >= *value_size) + { + strcpy(zjb->diag.service_name, "ZJBSYMB"); + ZDIAG_SET_MSG(&zjb->diag, "Symbol value size (%d) exceeds buffer capacity (%d) for symbol '%.32s'", + jsymbolEntry->jsyevals, *value_size, symbol); + zjb->diag.detail_rc = ZJB_RTNCD_INSUFFICIENT_BUFFER; + return RTNCD_FAILURE; + } + p = p + jsymbolEntry->jsyevalo; memcpy(value, p, jsymbolEntry->jsyevals); + // Null-terminate the string if there's space + if (jsymbolEntry->jsyevals < *value_size) + { + value[jsymbolEntry->jsyevals] = '\0'; + } + return RTNCD_SUCCESS; } @@ -190,11 +206,11 @@ int ZJBMMOD(ZJB *zjb, int type, int flags) zjb->diag.detail_rc = rc; if (ZJB_RTNCD_JES3_NOT_SUPPORTED == rc) { - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "JES3 is not supported"); + ZDIAG_SET_MSG(&zjb->diag, "JES3 is not supported"); } else { - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "Failed to get SSIBSSNM"); + ZDIAG_SET_MSG(&zjb->diag, "Failed to get SSIBSSNM"); } return RTNCD_FAILURE; } @@ -262,7 +278,7 @@ int ZJBMMOD(ZJB *zjb, int type, int flags) zjb->diag.service_rsn = ssjm.ssjmretn; zjb->diag.service_rsn_secondary = ssjm.ssjmret2; // Understanding reason codes from this SSOB: https://www.ibm.com/docs/en/zos/3.1.0?topic=85-output-parameters - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "IEFSSREQ rc was: '%d' SSOBRETN was: '%d', SSJMRETN was: '%d', SSJMRET2 was: '%d'", rc, ssob.ssobretn, ssjm.ssjmretn, ssjm.ssjmret2); + ZDIAG_SET_MSG(&zjb->diag, "IEFSSREQ rc was: '%d' SSOBRETN was: '%d', SSJMRETN was: '%d', SSJMRET2 was: '%d'", rc, ssob.ssobretn, ssjm.ssjmretn, ssjm.ssjmret2); return RTNCD_FAILURE; } @@ -273,15 +289,13 @@ int ZJBMMOD(ZJB *zjb, int type, int flags) if (zjb->jobid[0] != 0x00) { zjb->diag.detail_rc = ZJB_RTNCD_JOB_NOT_FOUND; - zjb->diag.e_msg_len = sprintf( - zjb->diag.e_msg, "No jobs found matching jobid '%.8s'", zjb->jobid); + ZDIAG_SET_MSG(&zjb->diag, "No jobs found matching jobid '%.8s'", zjb->jobid); } else { zjb->diag.detail_rc = ZJB_RTNCD_CORRELATOR_NOT_FOUND; - zjb->diag.e_msg_len = - sprintf(zjb->diag.e_msg, "No jobs found matching correlator '%.64s'", - zjb->correlator); + ZDIAG_SET_MSG(&zjb->diag, "No jobs found matching correlator '%.64s'", + zjb->correlator); } return RTNCD_FAILURE; } @@ -380,12 +394,14 @@ int ZJBMEMSG(ZJB *zjb, STAT *PTR64 stat, SSOB *PTR64 ssobp, int rc) #define STATLERR 8 if (STATLERR == ssobp->ssobretn && statrojb == stat->statreas) // skip if invalid job id { - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "Job ID '%.8s' was not valid", stat->statojbi); // STATREAS contains the reason + ZDIAG_SET_MSG(&zjb->diag, "Job ID '%.8s' was not valid", stat->statojbi); // STATREAS contains the reason } else { - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "IEFSSREQ rc was: '%d' SSOBRETN was: '%d', STATREAS was: '%d', STATREA2 was: '%d'", rc, ssobp->ssobretn, stat->statreas, stat->statrea2); // STATREAS contains the reason + ZDIAG_SET_MSG(&zjb->diag, "IEFSSREQ rc was: '%d' SSOBRETN was: '%d', STATREAS was: '%d', STATREA2 was: '%d'", rc, ssobp->ssobretn, stat->statreas, stat->statrea2); // STATREAS contains the reason } + + return rc; } int ZJBMTCOM(ZJB *zjb, STAT *PTR64 stat, ZJB_JOB_INFO **PTR64 job_info, int *entries) @@ -433,7 +449,7 @@ int ZJBMTCOM(ZJB *zjb, STAT *PTR64 stat, ZJB_JOB_INFO **PTR64 job_info, int *ent if (loop_control >= zjb->jobs_max) { zjb->diag.detail_rc = ZJB_RSNCD_MAX_JOBS_REACHED; - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "Reached maximum returned jobs requested %d", zjb->jobs_max); + ZDIAG_SET_MSG(&zjb->diag, "Reached maximum returned jobs requested %d", zjb->jobs_max); stat->stattype = statmem; // free storage rc = iefssreq(&ssobp); return RTNCD_WARNING; @@ -456,7 +472,7 @@ int ZJBMTCOM(ZJB *zjb, STAT *PTR64 stat, ZJB_JOB_INFO **PTR64 job_info, int *ent strcpy(zjb->diag.service_name, "iaztlkup"); // For information about the reason code, look for `tlkretcd` in "native/c/chdsect/iaztlkdf.h" // https://www.ibm.com/docs/en/zos/3.1.0?topic=80-text-lookup-service-iaztlkup - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "IAZTLKUP RC: '%d' reason: '%d'", statjqtrsp->statjqtr.sttrjid, rc, zjb->diag.detail_rc); + ZDIAG_SET_MSG(&zjb->diag, "IAZTLKUP RC: '%d' reason: '%d'", rc, zjb->diag.detail_rc); zjb->diag.detail_rc = ZJB_RTNCD_SERVICE_FAILURE; storage_free64(statjqtrsp); return RTNCD_FAILURE; @@ -555,15 +571,13 @@ int ZJBMLSDS(ZJB *PTR64 zjb, STATSEVB **PTR64 sysoutInfo, int *entries) if (zjb->jobid[0] != 0x00) { zjb->diag.detail_rc = ZJB_RTNCD_JOB_NOT_FOUND; - zjb->diag.e_msg_len = sprintf( - zjb->diag.e_msg, "No jobs found matching jobid '%.8s'", zjb->jobid); + ZDIAG_SET_MSG(&zjb->diag, "No jobs found matching jobid '%.8s'", zjb->jobid); } else { zjb->diag.detail_rc = ZJB_RTNCD_CORRELATOR_NOT_FOUND; - zjb->diag.e_msg_len = - sprintf(zjb->diag.e_msg, "No jobs found matching correlator '%.64s'", - zjb->correlator); + ZDIAG_SET_MSG(&zjb->diag, "No jobs found matching correlator '%.64s'", + zjb->correlator); } stat.stattype = statmem; // free storage @@ -582,12 +596,11 @@ int ZJBMLSDS(ZJB *PTR64 zjb, STATSEVB **PTR64 sysoutInfo, int *entries) zjb->diag.service_rc = ssob.ssobretn; zjb->diag.service_rsn = stat.statreas; zjb->diag.service_rsn_secondary = stat.statrea2; - zjb->diag.e_msg_len = - sprintf(zjb->diag.e_msg, - "IEFSSREQ rc was: '%d' SSOBRETN was: '%d', STATREAS was: '%d', " - "STATREA2 was: '%d'", - rc, ssob.ssobretn, stat.statreas, - stat.statrea2); // STATREAS contains the reason + ZDIAG_SET_MSG(&zjb->diag, + "IEFSSREQ rc was: '%d' SSOBRETN was: '%d', STATREAS was: '%d', " + "STATREA2 was: '%d'", + rc, ssob.ssobretn, stat.statreas, + stat.statrea2); // STATREAS contains the reason return RTNCD_FAILURE; } @@ -604,15 +617,13 @@ int ZJBMLSDS(ZJB *PTR64 zjb, STATSEVB **PTR64 sysoutInfo, int *entries) if (zjb->jobid[0] != 0x00) { zjb->diag.detail_rc = ZJB_RTNCD_JOB_NOT_FOUND; - zjb->diag.e_msg_len = sprintf( - zjb->diag.e_msg, "No jobs found matching jobid '%.8s'", zjb->jobid); + ZDIAG_SET_MSG(&zjb->diag, "No jobs found matching jobid '%.8s'", zjb->jobid); } else { zjb->diag.detail_rc = ZJB_RTNCD_CORRELATOR_NOT_FOUND; - zjb->diag.e_msg_len = - sprintf(zjb->diag.e_msg, "No jobs found matching correlator '%.64s'", - zjb->correlator); + ZDIAG_SET_MSG(&zjb->diag, "No jobs found matching correlator '%.64s'", + zjb->correlator); } zjb->diag.detail_rc = ZJB_RTNCD_JOB_NOT_FOUND; stat.stattype = statmem; // free storage @@ -638,7 +649,7 @@ int ZJBMLSDS(ZJB *PTR64 zjb, STATSEVB **PTR64 sysoutInfo, int *entries) stat.stattype = statmem; // free storage rc = iefssreq(&ssobp); // TODO(Kelosky): recovery zjb->diag.detail_rc = ZJB_RSNCD_MAX_JOBS_REACHED; - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "max DDs reached '%d', results truncated", zjb->dds_max); + ZDIAG_SET_MSG(&zjb->diag, "max DDs reached '%d', results truncated", zjb->dds_max); return RTNCD_WARNING; } @@ -693,7 +704,7 @@ int ZJBMLPRC(ZJB *zjb, char *buffer, int *buffer_size, int *entries) if (NULL == buffer || *buffer_size < MAX_DSN_ENTRY_SIZE) { zjb->diag.detail_rc = ZJB_RTNCD_INSUFFICIENT_BUFFER; - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "buffer is NULL or buffer size is less than '%d'", MAX_DSN_ENTRY_SIZE); + ZDIAG_SET_MSG(&zjb->diag, "buffer is NULL or buffer size is less than '%d'", MAX_DSN_ENTRY_SIZE); return RTNCD_FAILURE; } @@ -727,7 +738,7 @@ int ZJBMLPRC(ZJB *zjb, char *buffer, int *buffer_size, int *entries) strcpy(zjb->diag.service_name, "IEFSSREQ"); // TODO(Kelosky): recovery zjb->diag.service_rc = ssob.ssobretn; zjb->diag.service_rsn = ssjp.ssjpretn; - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "IEFSSREQ rc was: '%d' SSOBRETN was: '%d', SSJPRETN was: '%d'", rc, ssob.ssobretn, ssjp.ssjpretn); + ZDIAG_SET_MSG(&zjb->diag, "IEFSSREQ rc was: '%d' SSOBRETN was: '%d', SSJPRETN was: '%d'", rc, ssob.ssobretn, ssjp.ssjpretn); return RTNCD_FAILURE; } @@ -749,7 +760,7 @@ int ZJBMLPRC(ZJB *zjb, char *buffer, int *buffer_size, int *entries) if (*entries > MAX_DSN_ENTRIES) { zjb->diag.detail_rc = ZJB_RTNCD_INSUFFICIENT_BUFFER; - zjb->diag.e_msg_len = sprintf(zjb->diag.e_msg, "max DSN entries reached '%d', results truncated", MAX_DSN_ENTRIES); + ZDIAG_SET_MSG(&zjb->diag, "max DSN entries reached '%d', results truncated", MAX_DSN_ENTRIES); rc = RTNCD_FAILURE; break; } diff --git a/native/c/zjbm.h b/native/c/zjbm.h index 59d7eb031..fecaee403 100644 --- a/native/c/zjbm.h +++ b/native/c/zjbm.h @@ -40,12 +40,12 @@ extern "C" int ZJBMVIEW(ZJB *PTR64, ZJB_JOB_INFO **PTR64, int *PTR64); int ZJBMLIST(ZJB *PTR64, ZJB_JOB_INFO **PTR64, int *PTR64); - int ZJBMGJQ(ZJB *, SSOB *, STAT *, STATJQ * PTR32 * PTR32); + int ZJBMGJQ(ZJB *, SSOB *, STAT *, STATJQ *PTR32 *PTR32); int ZJBMEMSG(ZJB *, STAT *PTR64, SSOB *PTR64, int); int ZJBMTCOM(ZJB *PTR64, STAT *PTR64 stat, ZJB_JOB_INFO **PTR64, int *PTR64); int ZJBMLSDS(ZJB *PTR64, STATSEVB **PTR64, int *PTR64); int ZJBMLPRC(ZJB *PTR64, char *buffer, int *buffer_size, int *entries); - int ZJBSYMB(ZJB *PTR64, const char *PTR64, char *PTR64); + int ZJBSYMB(ZJB *PTR64, const char *PTR64, char *PTR64, int *value_size); int ZJBMPRG(ZJB *PTR64); int ZJBMCNL(ZJB *PTR64, int flags); int ZJBMHLD(ZJB *PTR64); diff --git a/native/c/zjson.hpp b/native/c/zjson.hpp index df124b0ef..767eff731 100644 --- a/native/c/zjson.hpp +++ b/native/c/zjson.hpp @@ -311,7 +311,7 @@ class Value // Forward declare friend functions and classes friend std::string value_to_json_string(const Value &value); friend Value parse_json_string(const std::string &json_str); - friend Value json_handle_to_value(JSON_INSTANCE *instance, KEY_HANDLE *key_handle); + friend Value json_handle_to_value(JSON_INSTANCE *instance, KEY_HANDLE *key_handle, int depth); // Friend template specializations for vector serialization template @@ -1439,10 +1439,20 @@ inline std::string unescape_json_string(const std::string &s) return res; } -inline Value json_handle_to_value(JSON_INSTANCE *instance, KEY_HANDLE *key_handle) +// Maximum allowed JSON nesting depth to prevent stack overflow +static constexpr int MAX_JSON_DEPTH = 64; + +inline Value json_handle_to_value(JSON_INSTANCE *instance, KEY_HANDLE *key_handle, int depth = 0) { try { + // Check depth limit to prevent unbounded recursion + if (depth >= MAX_JSON_DEPTH) + { + ZLOG_WARN("JSON parsing depth limit reached: %d", depth); + return Value(); + } + int type = 0; int rc = ZJSNGJST(instance, key_handle, &type); if (rc != 0) @@ -1537,7 +1547,7 @@ inline Value json_handle_to_value(JSON_INSTANCE *instance, KEY_HANDLE *key_handl { try { - Value element = json_handle_to_value(instance, &element_handle); + Value element = json_handle_to_value(instance, &element_handle, depth + 1); result.add_to_array(element); } catch (...) @@ -1576,7 +1586,7 @@ inline Value json_handle_to_value(JSON_INSTANCE *instance, KEY_HANDLE *key_handl try { std::string key_name(key_buffer_ptr, actual_length); - Value value = json_handle_to_value(instance, &value_handle); + Value value = json_handle_to_value(instance, &value_handle, depth + 1); result.add_to_object(key_name, value); } catch (...) @@ -1599,7 +1609,7 @@ inline Value json_handle_to_value(JSON_INSTANCE *instance, KEY_HANDLE *key_handl try { std::string key_name(key_buffer_ptr, actual_length); - Value value = json_handle_to_value(instance, &value_handle); + Value value = json_handle_to_value(instance, &value_handle, depth + 1); result.add_to_object(key_name, value); } catch (...) diff --git a/native/c/zlogger_metal.c b/native/c/zlogger_metal.c index 358099a11..f31e4865a 100644 --- a/native/c/zlogger_metal.c +++ b/native/c/zlogger_metal.c @@ -114,8 +114,15 @@ static void ZLGTIME(char *buffer, int buffer_size) /* Safety check - if conversion gives unreasonable result, use simple fallback */ if (unix_seconds == 0 || unix_seconds > 4000000000ULL) { /* Year 2096+ is unreasonable */ - /* Fallback to simple hex format */ - sprintf(buffer, "STCK:%016llX", clock_value); + /* Fallback to simple hex format safely */ + if (buffer_size >= 22) + { + sprintf(buffer, "STCK:%016llX", clock_value); + } + else if (buffer_size > 0) + { + buffer[0] = '\0'; + } return; } @@ -213,7 +220,7 @@ static int ZLGWRWTO(int level, const char *message) ? g_level_strings[level] : "UNKNOWN"; - wto_buf.len = sprintf(wto_buf.msg, "ZOWEX %s: %.100s", level_str, message); + wto_buf.len = sprintf(wto_buf.msg, "ZOWEX %.6s: %.90s", level_str, message); if (wto_buf.len >= (short)sizeof(wto_buf.msg)) { @@ -309,7 +316,12 @@ int ZLGINIT(const char *log_file_path, int *min_level) return 0; } - strcpy(logger->log_path, log_file_path); + strncpy(logger->log_path, log_file_path, sizeof(logger->log_path) - 1); + logger->log_path[sizeof(logger->log_path) - 1] = '\0'; + if (strlen(log_file_path) >= sizeof(logger->log_path)) + { + return -1; + } logger->min_level = *min_level; logger->use_wto = 1; @@ -330,7 +342,15 @@ int ZLGINIT(const char *log_file_path, int *min_level) BPXWDYN_PARM *bparm = (BPXWDYN_PARM *)p; BPXWDYN_RESPONSE *response = (BPXWDYN_RESPONSE *)(p + sizeof(BPXWDYN_PARM)); - bparm->len = sprintf(bparm->str, "%s", alloc_cmd); + /* Use precision specifier %.*s as snprintf is unavailable in Metal C */ + int cmd_result = sprintf(bparm->str, "%.*s", (int)(sizeof(bparm->str) - 1), alloc_cmd); + if (cmd_result >= sizeof(bparm->str)) + { + storage_release(size, p); + return -1; + } + bparm->len = cmd_result; + int rc = ZUTWDYN(bparm, response); if (rc != 0) @@ -373,9 +393,13 @@ int ZLGWRITE(int *level, const char *message) ? g_level_strings[*level] : "UNKNOWN"; - /* Format complete message */ - sprintf(formatted_msg, "[%s] [%s] %s", - timestamp, level_str, message); + /* Format complete message safely using %.*s (max message 900 chars to fit in 1024) */ + int format_result = sprintf(formatted_msg, "[%s] [%s] %.*s", + timestamp, level_str, 900, message); + if (format_result >= sizeof(formatted_msg)) + { + formatted_msg[sizeof(formatted_msg) - 1] = '\0'; + } /* Try DD writing first if available */ if (logger->use_dd) diff --git a/native/c/ztype.h b/native/c/ztype.h index d9bafc0eb..855cb67bb 100644 --- a/native/c/ztype.h +++ b/native/c/ztype.h @@ -18,6 +18,10 @@ #define RTNCD_SUCCESS 0 #define RTNCD_FAILURE -1 +#ifndef ZMIN +#define ZMIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + #if defined(__IBM_METAL__) || defined(__open_xl__) #define PTR32 __ptr32 #else @@ -97,4 +101,22 @@ typedef struct _ZEncode #define FIFO_CHUNK_SIZE 32768 +// Safe diagnostic message macro to prevent buffer overflow +#if defined(__IBM_METAL__) && !defined(__cplusplus) +#define ZDIAG_SET_MSG(diag, fmt, ...) \ + { \ + (diag)->e_msg_len = sprintf((diag)->e_msg, (fmt), ##__VA_ARGS__); \ + } +#else +#define ZDIAG_SET_MSG(diag, fmt, ...) \ + { \ + (diag)->e_msg_len = snprintf((diag)->e_msg, sizeof((diag)->e_msg), (fmt), ##__VA_ARGS__); \ + if ((diag)->e_msg_len >= sizeof((diag)->e_msg)) \ + { \ + (diag)->e_msg_len = sizeof((diag)->e_msg) - 1; \ + (diag)->e_msg[sizeof((diag)->e_msg) - 1] = '\0'; \ + } \ + } +#endif + #endif diff --git a/native/c/zusf.cpp b/native/c/zusf.cpp index 74532eda4..2504cf13d 100644 --- a/native/c/zusf.cpp +++ b/native/c/zusf.cpp @@ -133,13 +133,13 @@ int zusf_get_file_ccsid(ZUSF *zusf, const std::string &file) struct stat file_stats; if (stat(file.c_str(), &file_stats) == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' does not exist", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' does not exist", file.c_str()); return RTNCD_FAILURE; } if (S_ISDIR(file_stats.st_mode)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' is a directory", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' is a directory", file.c_str()); return RTNCD_FAILURE; } @@ -854,13 +854,13 @@ int zusf_copy_file_or_dir(ZUSF *zusf, const std::string &source_path, const std: if (!zusf_is_valid_path(source_path) || !zusf_is_valid_path(destination_path)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Source or target path is empty or too long"); + ZDIAG_SET_MSG(&zusf->diag, "Source or target path is empty or too long"); return RTNCD_FAILURE; } if (options.follow_symlinks && !options.recursive) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "follow symlinks option requires setting the recursive flag"); + ZDIAG_SET_MSG(&zusf->diag, "follow symlinks option requires setting the recursive flag"); return RTNCD_FAILURE; } struct stat buf; @@ -868,7 +868,7 @@ int zusf_copy_file_or_dir(ZUSF *zusf, const std::string &source_path, const std: { if (S_ISFIFO(buf.st_mode)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "we do not support copying from named pipes"); + ZDIAG_SET_MSG(&zusf->diag, "we do not support copying from named pipes"); return RTNCD_FAILURE; } } @@ -877,13 +877,13 @@ int zusf_copy_file_or_dir(ZUSF *zusf, const std::string &source_path, const std: { if (S_ISFIFO(buf.st_mode)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "we do not support copying to named pipes"); + ZDIAG_SET_MSG(&zusf->diag, "we do not support copying to named pipes"); return RTNCD_FAILURE; } } std::vector command_parameters; - command_parameters.reserve(6); + command_parameters.reserve(7); if (options.recursive) { @@ -901,6 +901,7 @@ int zusf_copy_file_or_dir(ZUSF *zusf, const std::string &source_path, const std: { command_parameters.emplace_back("-f"); } + command_parameters.emplace_back("--"); command_parameters.emplace_back(source_path); command_parameters.emplace_back(destination_path); @@ -908,7 +909,7 @@ int zusf_copy_file_or_dir(ZUSF *zusf, const std::string &source_path, const std: int rc = zut_run_program("cp", command_parameters, stdout_resp, stderr_resp); if (rc > 0) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to copy %s to %s, errno: %d\nstderr: %s", source_path.c_str(), destination_path.c_str(), rc, stderr_resp.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Failed to copy %s to %s, errno: %d\nstderr: %s", source_path.c_str(), destination_path.c_str(), rc, stderr_resp.c_str()); return RTNCD_FAILURE; } return rc; @@ -931,15 +932,15 @@ int zusf_create_uss_file_or_dir(ZUSF *zusf, const std::string &file, mode_t mode { if (S_ISREG(file_stats.st_mode)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "File '%s' already exists", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "File '%s' already exists", file.c_str()); } else if (S_ISDIR(file_stats.st_mode)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Directory '%s' already exists", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Directory '%s' already exists", file.c_str()); } else { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' already exists! Mode: '%08o'", file.c_str(), file_stats.st_mode); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' already exists! Mode: '%08o'", file.c_str(), file_stats.st_mode); } return RTNCD_WARNING; } @@ -963,7 +964,7 @@ int zusf_create_uss_file_or_dir(ZUSF *zusf, const std::string &file, mode_t mode const auto rc = mkdir(file.c_str(), mode); if (0 != rc) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to create directory '%s', errno: %d", file.c_str(), errno); + ZDIAG_SET_MSG(&zusf->diag, "Failed to create directory '%s', errno: %d", file.c_str(), errno); } chmod(file.c_str(), mode); return rc; @@ -979,7 +980,7 @@ int zusf_create_uss_file_or_dir(ZUSF *zusf, const std::string &file, mode_t mode } } - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not create '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not create '%s'", file.c_str()); return RTNCD_FAILURE; } @@ -987,7 +988,7 @@ int zusf_move_uss_file_or_dir(ZUSF *zusf, const std::string &source, const std:: { if (!zusf_is_valid_path(source) || !zusf_is_valid_path(target)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Source or target path is empty or too long"); + ZDIAG_SET_MSG(&zusf->diag, "Source or target path is empty or too long"); return RTNCD_FAILURE; } @@ -998,14 +999,14 @@ int zusf_move_uss_file_or_dir(ZUSF *zusf, const std::string &source, const std:: struct stat source_stats; if (lstat(source.c_str(), &source_stats) == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Source path '%s' does not exist", truncated_source.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Source path '%s' does not exist", truncated_source.c_str()); return RTNCD_FAILURE; } // simple string compare for source and target if (strcmp(source.c_str(), target.c_str()) == 0) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Source '%s' and target '%s' are identical", truncated_source.c_str(), truncated_target.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Source '%s' and target '%s' are identical", truncated_source.c_str(), truncated_target.c_str()); return RTNCD_FAILURE; } @@ -1014,7 +1015,7 @@ int zusf_move_uss_file_or_dir(ZUSF *zusf, const std::string &source, const std:: char resolved_source[PATH_MAX]; if (stat(source.c_str(), &source_stats) == 0 && realpath(source.c_str(), resolved_source) == nullptr) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to resolve source path '%s'; errno: %d", truncated_source.c_str(), errno); + ZDIAG_SET_MSG(&zusf->diag, "Failed to resolve source path '%s'; errno: %d", truncated_source.c_str(), errno); return RTNCD_FAILURE; } @@ -1029,7 +1030,7 @@ int zusf_move_uss_file_or_dir(ZUSF *zusf, const std::string &source, const std:: // if target exists and force is not set, return failure if (!force) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Target path '%s' already exists", truncated_target.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Target path '%s' already exists", truncated_target.c_str()); return RTNCD_FAILURE; } @@ -1037,14 +1038,14 @@ int zusf_move_uss_file_or_dir(ZUSF *zusf, const std::string &source, const std:: // resolve target path, save it to resolved_target if (stat(target.c_str(), &target_stats) == 0 && realpath(target.c_str(), resolved_target) == nullptr) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to resolve target path '%s'; errno: %d", truncated_target.c_str(), errno); + ZDIAG_SET_MSG(&zusf->diag, "Failed to resolve target path '%s'; errno: %d", truncated_target.c_str(), errno); return RTNCD_FAILURE; } // check if paths are identical if (strcmp(resolved_source, resolved_target) == 0) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Source '%s' and target '%s' are identical", truncated_source.c_str(), truncated_target.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Source '%s' and target '%s' are identical", truncated_source.c_str(), truncated_target.c_str()); return RTNCD_FAILURE; } @@ -1052,24 +1053,24 @@ int zusf_move_uss_file_or_dir(ZUSF *zusf, const std::string &source, const std:: // check if source is a directory and target is not if (S_ISDIR(source_stats.st_mode) && !target_is_dir) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Cannot move directory '%s'. Target '%s' is not a directory", truncated_source.c_str(), truncated_target.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Cannot move directory '%s'. Target '%s' is not a directory", truncated_source.c_str(), truncated_target.c_str()); return RTNCD_FAILURE; } // check if source is a pipe and target is not if (S_ISFIFO(source_stats.st_mode) && !S_ISFIFO(target_stats.st_mode)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Cannot move pipe '%s'. Target '%s' is not a pipe", truncated_source.c_str(), truncated_target.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Cannot move pipe '%s'. Target '%s' is not a pipe", truncated_source.c_str(), truncated_target.c_str()); return RTNCD_FAILURE; } } // TODO(zFernand0): Use std::filesystem::rename instead of rename when C++17 is available std::string stdout_resp, stderr_resp; - int rc = zut_run_program("mv", {source, target}, stdout_resp, stderr_resp); + int rc = zut_run_program("mv", {"--", source, target}, stdout_resp, stderr_resp); if (rc != 0) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to move file or directory from '%s' to '%s', errno: %d", truncated_source.c_str(), truncated_target.c_str(), rc); + ZDIAG_SET_MSG(&zusf->diag, "Failed to move file or directory from '%s' to '%s', errno: %d", truncated_source.c_str(), truncated_target.c_str(), rc); return RTNCD_FAILURE; } @@ -1220,14 +1221,14 @@ int zusf_list_uss_file_path(ZUSF *zusf, const std::string &file, std::string &re { if (!zusf_is_valid_path(file)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "File path is empty or too long"); + ZDIAG_SET_MSG(&zusf->diag, "File path is empty or too long"); return RTNCD_FAILURE; } // TODO(zFernand0): Handle `*` and other bash-expansion rules struct stat file_stats; if (stat(file.c_str(), &file_stats) == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' does not exist", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' does not exist", file.c_str()); return RTNCD_FAILURE; } @@ -1241,7 +1242,7 @@ int zusf_list_uss_file_path(ZUSF *zusf, const std::string &file, std::string &re if (!S_ISDIR(file_stats.st_mode)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' is not a directory", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' is not a directory", file.c_str()); return RTNCD_FAILURE; } @@ -1278,7 +1279,7 @@ int zusf_list_uss_file_path(ZUSF *zusf, const std::string &file, std::string &re std::vector entry_names; if (zusf_collect_directory_entries_recursive(zusf, file, entry_names, options) != RTNCD_SUCCESS) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open directory '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open directory '%s'", file.c_str()); return RTNCD_FAILURE; } @@ -1290,7 +1291,7 @@ int zusf_list_uss_file_path(ZUSF *zusf, const std::string &file, std::string &re struct stat child_stats; if (lstat(child_path.c_str(), &child_stats) != 0) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not stat child path '%s'", child_path.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not stat child path '%s'", child_path.c_str()); return RTNCD_FAILURE; } @@ -1315,7 +1316,7 @@ int zusf_read_from_uss_file(ZUSF *zusf, const std::string &file, std::string &re std::ifstream in(file.c_str(), zusf->encoding_opts.data_type == eDataTypeBinary ? std::ifstream::in | std::ifstream::binary : std::ifstream::in); if (!in.is_open()) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open file '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open file '%s'", file.c_str()); return RTNCD_FAILURE; } @@ -1363,7 +1364,7 @@ int zusf_read_from_uss_file(ZUSF *zusf, const std::string &file, std::string &re } catch (std::exception &e) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to convert input data from %s to %s", source_encoding.c_str(), encoding_to_use.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Failed to convert input data from %s to %s", source_encoding.c_str(), encoding_to_use.c_str()); return RTNCD_FAILURE; } if (!temp.empty()) @@ -1389,7 +1390,7 @@ int zusf_read_from_uss_file_streamed(ZUSF *zusf, const std::string &file, const { if (content_len == nullptr) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "content_len must be a valid size_t pointer"); + ZDIAG_SET_MSG(&zusf->diag, "content_len must be a valid size_t pointer"); return RTNCD_FAILURE; } @@ -1397,14 +1398,14 @@ int zusf_read_from_uss_file_streamed(ZUSF *zusf, const std::string &file, const FileGuard fin(file.c_str(), zusf->encoding_opts.data_type == eDataTypeBinary ? "rb" : "r"); if (!fin) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open file '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open file '%s'", file.c_str()); return RTNCD_FAILURE; } struct stat st; if (stat(file.c_str(), &st) != 0) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not stat file '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not stat file '%s'", file.c_str()); return RTNCD_FAILURE; } @@ -1416,14 +1417,14 @@ int zusf_read_from_uss_file_streamed(ZUSF *zusf, const std::string &file, const int fifo_fd = open(pipe.c_str(), O_WRONLY); if (fifo_fd == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "open() failed on output pipe '%s', errno: %d", pipe.c_str(), errno); + ZDIAG_SET_MSG(&zusf->diag, "open() failed on output pipe '%s', errno: %d", pipe.c_str(), errno); return RTNCD_FAILURE; } FileGuard fout(fifo_fd, "w"); if (!fout) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open output pipe '%s'", pipe.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open output pipe '%s'", pipe.c_str()); close(fifo_fd); return RTNCD_FAILURE; } @@ -1466,7 +1467,7 @@ int zusf_read_from_uss_file_streamed(ZUSF *zusf, const std::string &file, const cd = iconv_open(source_encoding.c_str(), encoding_to_use.c_str()); if (cd == (iconv_t)(-1)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Cannot open converter from %s to %s", encoding_to_use.c_str(), source_encoding.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Cannot open converter from %s to %s", encoding_to_use.c_str(), source_encoding.c_str()); return RTNCD_FAILURE; } } @@ -1487,7 +1488,7 @@ int zusf_read_from_uss_file_streamed(ZUSF *zusf, const std::string &file, const catch (std::exception &e) { iconv_close(cd); - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to convert input data from %s to %s", encoding_to_use.c_str(), source_encoding.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Failed to convert input data from %s to %s", encoding_to_use.c_str(), source_encoding.c_str()); return RTNCD_FAILURE; } } @@ -1522,7 +1523,7 @@ int zusf_read_from_uss_file_streamed(ZUSF *zusf, const std::string &file, const catch (std::exception &e) { iconv_close(cd); - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to flush encoding state"); + ZDIAG_SET_MSG(&zusf->diag, "Failed to flush encoding state"); return RTNCD_FAILURE; } @@ -1559,7 +1560,7 @@ int zusf_write_to_uss_file(ZUSF *zusf, const std::string &file, std::string &dat const auto current_etag = zut_build_etag(file_stats.st_mtime, file_stats.st_size); if (current_etag != zusf->etag) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Etag mismatch: expected %s, actual %s", zusf->etag, current_etag.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Etag mismatch: expected %s, actual %s", zusf->etag, current_etag.c_str()); return RTNCD_FAILURE; } } @@ -1601,7 +1602,7 @@ int zusf_write_to_uss_file(ZUSF *zusf, const std::string &file, std::string &dat } catch (std::exception &e) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to convert input data from %s to %s", source_encoding.c_str(), encoding_to_use.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Failed to convert input data from %s to %s", source_encoding.c_str(), encoding_to_use.c_str()); return RTNCD_FAILURE; } } @@ -1612,7 +1613,7 @@ int zusf_write_to_uss_file(ZUSF *zusf, const std::string &file, std::string &dat FileGuard fp(file.c_str(), mode); if (!fp) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open '%s' for writing", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open '%s' for writing", file.c_str()); return RTNCD_FAILURE; } @@ -1621,7 +1622,7 @@ int zusf_write_to_uss_file(ZUSF *zusf, const std::string &file, std::string &dat size_t bytes_written = fwrite(temp.data(), 1, temp.size(), fp); if (bytes_written != temp.size()) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to write to '%s' (possibly out of space)", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Failed to write to '%s' (possibly out of space)", file.c_str()); return RTNCD_FAILURE; } } @@ -1635,8 +1636,8 @@ int zusf_write_to_uss_file(ZUSF *zusf, const std::string &file, std::string &dat struct stat new_stats; if (stat(file.c_str(), &new_stats) == -1) { - zusf->diag.e_msg_len = sprintf( - zusf->diag.e_msg, + zusf->diag.e_msg_len = snprintf( + zusf->diag.e_msg, sizeof(zusf->diag.e_msg), "Could not stat file '%s' after writing", file.c_str()); return RTNCD_FAILURE; @@ -1663,7 +1664,7 @@ int zusf_write_to_uss_file_streamed(ZUSF *zusf, const std::string &file, const s // TODO(zFernand0): Avoid overriding existing files if (content_len == nullptr) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "content_len must be a valid size_t pointer"); + ZDIAG_SET_MSG(&zusf->diag, "content_len must be a valid size_t pointer"); return RTNCD_FAILURE; } @@ -1698,7 +1699,7 @@ int zusf_write_to_uss_file_streamed(ZUSF *zusf, const std::string &file, const s const auto current_etag = zut_build_etag(file_stats.st_mtime, file_stats.st_size); if (current_etag != zusf->etag) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Etag mismatch: expected %s, actual %s", zusf->etag, current_etag.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Etag mismatch: expected %s, actual %s", zusf->etag, current_etag.c_str()); return RTNCD_FAILURE; } } @@ -1710,21 +1711,21 @@ int zusf_write_to_uss_file_streamed(ZUSF *zusf, const std::string &file, const s FileGuard fout(file.c_str(), zusf->encoding_opts.data_type == eDataTypeBinary ? "wb" : "w"); if (!fout) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open '%s'", file.c_str()); return RTNCD_FAILURE; } int fifo_fd = open(pipe.c_str(), O_RDONLY); if (fifo_fd == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "open() failed on input pipe '%s', errno: %d", pipe.c_str(), errno); + ZDIAG_SET_MSG(&zusf->diag, "open() failed on input pipe '%s', errno: %d", pipe.c_str(), errno); return RTNCD_FAILURE; } FileGuard fin(fifo_fd, "r"); if (!fin) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open input pipe '%s'", pipe.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open input pipe '%s'", pipe.c_str()); close(fifo_fd); return RTNCD_FAILURE; } @@ -1744,7 +1745,7 @@ int zusf_write_to_uss_file_streamed(ZUSF *zusf, const std::string &file, const s cd = iconv_open(encoding_to_use.c_str(), source_encoding.c_str()); if (cd == (iconv_t)(-1)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Cannot open converter from %s to %s", source_encoding.c_str(), encoding_to_use.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Cannot open converter from %s to %s", source_encoding.c_str(), encoding_to_use.c_str()); return RTNCD_FAILURE; } } @@ -1767,7 +1768,7 @@ int zusf_write_to_uss_file_streamed(ZUSF *zusf, const std::string &file, const s catch (std::exception &e) { iconv_close(cd); - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to convert input data from %s to %s", source_encoding.c_str(), encoding_to_use.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Failed to convert input data from %s to %s", source_encoding.c_str(), encoding_to_use.c_str()); return RTNCD_FAILURE; } } @@ -1807,7 +1808,7 @@ int zusf_write_to_uss_file_streamed(ZUSF *zusf, const std::string &file, const s catch (std::exception &e) { iconv_close(cd); - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to flush encoding state"); + ZDIAG_SET_MSG(&zusf->diag, "Failed to flush encoding state"); return RTNCD_FAILURE; } @@ -1817,7 +1818,7 @@ int zusf_write_to_uss_file_streamed(ZUSF *zusf, const std::string &file, const s const int flush_rc = fflush(fout); if (truncated || flush_rc != 0) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to write to '%s' (possibly out of space)", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Failed to write to '%s' (possibly out of space)", file.c_str()); return RTNCD_FAILURE; } @@ -1828,7 +1829,7 @@ int zusf_write_to_uss_file_streamed(ZUSF *zusf, const std::string &file, const s if (stat(file.c_str(), &file_stats) == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' does not exist", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' does not exist", file.c_str()); return RTNCD_FAILURE; } @@ -1854,13 +1855,13 @@ int zusf_chmod_uss_file_or_dir(ZUSF *zusf, const std::string &file, mode_t mode, struct stat file_stats; if (stat(file.c_str(), &file_stats) == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' does not exist", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' does not exist", file.c_str()); return RTNCD_FAILURE; } if (!recursive && S_ISDIR(file_stats.st_mode)) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' is a folder and recursive is false", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' is a folder and recursive is false", file.c_str()); return RTNCD_FAILURE; } @@ -1870,7 +1871,7 @@ int zusf_chmod_uss_file_or_dir(ZUSF *zusf, const std::string &file, mode_t mode, DIR *dir = opendir(file.c_str()); if (dir == nullptr) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open directory '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open directory '%s'", file.c_str()); return RTNCD_FAILURE; } struct dirent *entry; @@ -1900,14 +1901,14 @@ int zusf_delete_uss_item(ZUSF *zusf, const std::string &file, bool recursive) struct stat file_stats; if (lstat(file.c_str(), &file_stats) == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' does not exist", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' does not exist", file.c_str()); return RTNCD_FAILURE; } const auto is_dir = S_ISDIR(file_stats.st_mode); if (is_dir && !recursive) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' is a directory and recursive was false", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' is a directory and recursive was false", file.c_str()); return RTNCD_FAILURE; } @@ -1916,7 +1917,7 @@ int zusf_delete_uss_item(ZUSF *zusf, const std::string &file, bool recursive) DIR *dir = opendir(file.c_str()); if (dir == nullptr) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open directory '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open directory '%s'", file.c_str()); return RTNCD_FAILURE; } struct dirent *entry; @@ -1929,7 +1930,7 @@ int zusf_delete_uss_item(ZUSF *zusf, const std::string &file, bool recursive) if (lstat(child_path.c_str(), &child_stats) == -1) { closedir(dir); - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not stat child path '%s'", child_path.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not stat child path '%s'", child_path.c_str()); return RTNCD_FAILURE; } @@ -1947,7 +1948,7 @@ int zusf_delete_uss_item(ZUSF *zusf, const std::string &file, bool recursive) const auto rc = is_dir ? rmdir(file.c_str()) : remove(file.c_str()); if (0 != rc) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not delete '%s', rc: %d", file.c_str(), errno); + ZDIAG_SET_MSG(&zusf->diag, "Could not delete '%s', rc: %d", file.c_str(), errno); return RTNCD_FAILURE; } @@ -2055,14 +2056,14 @@ int zusf_chown_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s // Verify target exists and capture current metadata if (stat(file.c_str(), &file_stats) == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' does not exist", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' does not exist", file.c_str()); return RTNCD_FAILURE; } // Refuse to descend into a directory if caller didn’t request recursion if (S_ISDIR(file_stats.st_mode) && !recursive) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' is a folder and recursive is false", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' is a folder and recursive is false", file.c_str()); return RTNCD_FAILURE; } @@ -2083,7 +2084,7 @@ int zusf_chown_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s if (!resolve_uid_from_str(userPart, uid)) { errno = EINVAL; - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "chown error: invalid user '%s'", userPart.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "chown error: invalid user '%s'", userPart.c_str()); return RTNCD_FAILURE; } @@ -2091,7 +2092,7 @@ int zusf_chown_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s if (!resolve_gid_from_str(groupPart, gid)) { errno = EINVAL; - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "chown error: invalid group '%s'", groupPart.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "chown error: invalid group '%s'", groupPart.c_str()); return RTNCD_FAILURE; } @@ -2099,7 +2100,7 @@ int zusf_chown_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s if (uid == (uid_t)-1 && gid == (gid_t)-1) { errno = EINVAL; - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "chown error: neither user nor group specified"); + ZDIAG_SET_MSG(&zusf->diag, "chown error: neither user nor group specified"); return RTNCD_FAILURE; } @@ -2111,7 +2112,7 @@ int zusf_chown_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s const auto rc = chown(file.c_str(), uid, gid); if (rc != 0) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "chown failed for path '%s', errno %d", file.c_str(), errno); + ZDIAG_SET_MSG(&zusf->diag, "chown failed for path '%s', errno %d", file.c_str(), errno); return RTNCD_FAILURE; } @@ -2121,7 +2122,7 @@ int zusf_chown_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s DIR *dir = opendir(file.c_str()); if (!dir) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open directory '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open directory '%s'", file.c_str()); return RTNCD_FAILURE; } @@ -2135,7 +2136,7 @@ int zusf_chown_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s if (stat(child_path.c_str(), &child_stats) == -1) { closedir(dir); - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not stat child path '%s'", child_path.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not stat child path '%s'", child_path.c_str()); return RTNCD_FAILURE; } @@ -2158,7 +2159,7 @@ int zusf_chtag_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s struct stat file_stats; if (stat(file.c_str(), &file_stats) == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Path '%s' does not exist", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Path '%s' does not exist", file.c_str()); return RTNCD_FAILURE; } @@ -2178,7 +2179,7 @@ int zusf_chtag_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s ccsid = zusf_get_ccsid_from_display_name(tag); if (ccsid == -1) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Invalid tag '%s' - not a valid CCSID or display name", tag.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Invalid tag '%s' - not a valid CCSID or display name", tag.c_str()); return RTNCD_FAILURE; } } @@ -2194,7 +2195,7 @@ int zusf_chtag_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s const auto rc = __chattr((char *)file.c_str(), &attr, sizeof(attr)); if (0 != rc) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Failed to update attributes for path '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Failed to update attributes for path '%s'", file.c_str()); return RTNCD_FAILURE; } } @@ -2203,7 +2204,7 @@ int zusf_chtag_uss_file_or_dir(ZUSF *zusf, const std::string &file, const std::s DIR *dir = opendir(file.c_str()); if (dir == nullptr) { - zusf->diag.e_msg_len = sprintf(zusf->diag.e_msg, "Could not open directory '%s'", file.c_str()); + ZDIAG_SET_MSG(&zusf->diag, "Could not open directory '%s'", file.c_str()); return RTNCD_FAILURE; } struct dirent *entry; diff --git a/native/c/zut.cpp b/native/c/zut.cpp index e60e42096..3ad0a37bb 100644 --- a/native/c/zut.cpp +++ b/native/c/zut.cpp @@ -394,13 +394,14 @@ int zut_substitute_symbol(const std::string &pattern, std::string &result) } memset(parms, 0x00, sizeof(SYMBOL_DATA)); - if (pattern.size() > sizeof(parms->input)) + if (pattern.size() >= sizeof(parms->input)) { free(parms); return RTNCD_FAILURE; } - strcpy(parms->input, pattern.c_str()); + strncpy(parms->input, pattern.c_str(), sizeof(parms->input) - 1); + parms->input[sizeof(parms->input) - 1] = '\0'; parms->length = std::strlen(pattern.c_str()); int rc = ZUTSYMBP(parms); if (RTNCD_SUCCESS != rc) @@ -408,6 +409,7 @@ int zut_substitute_symbol(const std::string &pattern, std::string &result) free(parms); return rc; } + parms->output[sizeof(parms->output) - 1] = '\0'; result += std::string(parms->output); free(parms); return RTNCD_SUCCESS; @@ -439,6 +441,11 @@ int zut_bpxwdyn_common(const std::string &parm, unsigned int *code, std::string memset(p, 0x00, sizeof(BPXWDYN_PARM) + sizeof(BPXWDYN_RESPONSE)); BPXWDYN_PARM *bparm = (BPXWDYN_PARM *)p; + if (parm.size() >= sizeof(bparm->str)) + { + return RTNCD_FAILURE; + } + BPXWDYN_RESPONSE *response = (BPXWDYN_RESPONSE *)(p + sizeof(BPXWDYN_PARM)); if (ddname == "RTDDN") @@ -450,7 +457,7 @@ int zut_bpxwdyn_common(const std::string &parm, unsigned int *code, std::string bparm->rtdsn = 1; // set bit flag indicating we want to return the DS name } - bparm->len = sprintf(bparm->str, "%s", parm.c_str()); + bparm->len = snprintf(bparm->str, sizeof(bparm->str), "%s", parm.c_str()); int rc = ZUTWDYN(bparm, response); @@ -672,11 +679,11 @@ void zut_print_string_as_bytes(std::string &input, std::ostream *out_stream) { if (p == (input.data() + input.length() - 1)) { - sprintf(buf, "%02x", (unsigned char)*p); + snprintf(buf, sizeof(buf), "%02x", (unsigned char)*p); } else { - sprintf(buf, "%02x ", (unsigned char)*p); + snprintf(buf, sizeof(buf), "%02x ", (unsigned char)*p); } output_stream << buf; } @@ -753,14 +760,14 @@ size_t zut_iconv(iconv_t cd, ZConvData &data, ZDIAG &diag, bool flush_state) // If an error occurred, throw an exception with iconv's return code and errno if (-1 == rc) { - diag.e_msg_len = sprintf(diag.e_msg, "[zut_iconv] Error when converting characters. rc=%zu,errno=%d", rc, errno); + ZDIAG_SET_MSG(&diag, "[zut_iconv] Error when converting characters. rc=%zu,errno=%d", rc, errno); return -1; } // "If the input conversion is stopped... the value pointed to by inbytesleft will be nonzero and errno is set to indicate the condition" if (0 != input_bytes_remaining) { - diag.e_msg_len = sprintf(diag.e_msg, "[zut_iconv] Failed to convert all input bytes. rc=%zu,errno=%d", rc, errno); + ZDIAG_SET_MSG(&diag, "[zut_iconv] Failed to convert all input bytes. rc=%zu,errno=%d", rc, errno); return -1; } @@ -770,7 +777,7 @@ size_t zut_iconv(iconv_t cd, ZConvData &data, ZDIAG &diag, bool flush_state) size_t flush_rc = iconv(cd, nullptr, nullptr, &data.output_iter, &output_bytes_remaining); if (-1 == flush_rc) { - diag.e_msg_len = sprintf(diag.e_msg, "[zut_iconv] Error flushing shift state. rc=%zu,errno=%d", flush_rc, errno); + ZDIAG_SET_MSG(&diag, "[zut_iconv] Error flushing shift state. rc=%zu,errno=%d", flush_rc, errno); return -1; } } @@ -798,7 +805,7 @@ std::vector zut_iconv_flush(iconv_t cd, ZDIAG &diag) size_t flush_rc = iconv(cd, nullptr, nullptr, &output_iter, &output_bytes_remaining); if (-1 == flush_rc) { - diag.e_msg_len = sprintf(diag.e_msg, "[zut_iconv_flush] Error flushing shift state. rc=%zu,errno=%d", flush_rc, errno); + ZDIAG_SET_MSG(&diag, "[zut_iconv_flush] Error flushing shift state. rc=%zu,errno=%d", flush_rc, errno); return std::vector(); // Return empty vector on error } @@ -844,7 +851,7 @@ std::vector zut_encode(const char *input_str, const size_t input_size, con iconv_t cd = iconv_open(to_encoding.c_str(), from_encoding.c_str()); if (cd == (iconv_t)(-1)) { - diag.e_msg_len = sprintf(diag.e_msg, "Cannot open converter from %s to %s", from_encoding.c_str(), to_encoding.c_str()); + ZDIAG_SET_MSG(&diag, "Cannot open converter from %s to %s", from_encoding.c_str(), to_encoding.c_str()); return std::vector(); } @@ -972,7 +979,7 @@ int zut_loop_dynalloc(ZDIAG &diag, const std::vector &list) diag.detail_rc = ZUT_RTNCD_SERVICE_FAILURE; diag.service_rc = rc; strcpy(diag.service_name, "bpxwdyn"); - diag.e_msg_len = sprintf(diag.e_msg, "bpxwdyn failed with '%s' rc: '%d', emsg: '%s'", diag.service_name, rc, response.c_str()); + ZDIAG_SET_MSG(&diag, "bpxwdyn failed with '%s' rc: '%d', emsg: '%s'", diag.service_name, rc, response.c_str()); return RTNCD_FAILURE; } } @@ -991,13 +998,13 @@ int zut_free_dynalloc_dds(ZDIAG &diag, const std::vector &list) const auto dd_start = alloc_dd.find("dd("); if (dd_start == std::string::npos) { - diag.e_msg_len = sprintf(diag.e_msg, "Invalid format in DD alloc string: %s", entry.c_str()); + ZDIAG_SET_MSG(&diag, "Invalid format in DD alloc string: %s", entry.c_str()); return RTNCD_FAILURE; } const auto paren_end = alloc_dd.find(")", dd_start + 3); if (paren_end == std::string::npos) { - diag.e_msg_len = sprintf(diag.e_msg, "Invalid format in DD alloc string: %s", entry.c_str()); + ZDIAG_SET_MSG(&diag, "Invalid format in DD alloc string: %s", entry.c_str()); return RTNCD_FAILURE; } free_dds.push_back("free " + alloc_dd.substr(dd_start, paren_end - dd_start + 1)); diff --git a/native/c/zutm.c b/native/c/zutm.c index 0ae7406ee..23cc8f2cf 100644 --- a/native/c/zutm.c +++ b/native/c/zutm.c @@ -102,7 +102,7 @@ int ZUTWDYN(BPXWDYN_PARM *parm, BPXWDYN_RESPONSE *response) msg_index--; input_parameters--; } - parameters[msg_index].len = sprintf(parameters[msg_index].str, "MSG"); + parameters[msg_index].len = sprintf(parameters[msg_index].str, "%s", "MSG"); int index = 0; @@ -169,7 +169,13 @@ int ZUTWDYN(BPXWDYN_PARM *parm, BPXWDYN_RESPONSE *response) return (0 != rc) ? ZUT_BPXWDYN_SERVICE_FAILURE : RTNCD_SUCCESS; } // otherwise, append the message to the response - int len = sprintf(respp, "%.*s\n", parameters[i + input_parameters].len, parameters[i + input_parameters].str); + size_t remaining = sizeof(response->response) - (respp - response->response); + if (remaining <= 1) + break; + size_t write_len = parameters[i + input_parameters].len; + if (write_len > remaining - 2) + write_len = remaining - 2; + int len = sprintf(respp, "%.*s\n", (int)write_len, parameters[i + input_parameters].str); respp = respp + len; } @@ -232,7 +238,7 @@ int ZUTSRCH(const char *parms) int rc = 0; PARMS p = {0}; - p.len = sprintf(p.parms, "%s", parms); + p.len = sprintf(p.parms, "%.*s", (int)(sizeof(p.parms) - 1), parms); ISRSUPC search = (ISRSUPC)load_module31("ISRSUPC"); rc = search(&p); @@ -253,7 +259,7 @@ int ZUTRUN(ZDIAG *diag, const char *program, const char *parms) PARMS pstruct = {0}; if (parms) { - pstruct.len = sprintf(pstruct.parms, "%s", parms); + pstruct.len = sprintf(pstruct.parms, "%.*s", (int)(sizeof(pstruct.parms) - 1), parms); } PARMS *pptr = &pstruct; @@ -283,7 +289,7 @@ int ZUTRUN(ZDIAG *diag, const char *program, const char *parms) } else { - diag->e_msg_len = sprintf(diag->e_msg, "Load failure for program '%s', not found", name_truncated); + ZDIAG_SET_MSG(diag, "Load failure for program '%.8s', not found", name_truncated); diag->detail_rc = ZUT_RTNCD_LOAD_FAILURE; return RTNCD_FAILURE; } @@ -308,7 +314,7 @@ int ZUTEDSCT() CCNEDSCT convert = (CCNEDSCT)load_module31("CCNEDSCT"); EDSCT_PARMS p = {0}; - p.len = sprintf(p.parms, "PPCOND,EQUATE(DEF),BITF0XL,HDRSKIP,UNIQ,LP64,LEGACY,SECT(ALL)"); + p.len = sprintf(p.parms, "%.100s", "PPCOND,EQUATE(DEF),BITF0XL,HDRSKIP,UNIQ,LP64,LEGACY,SECT(ALL)"); rc = convert(&p); delete_module("CCNEDSCT"); return rc; @@ -376,8 +382,8 @@ void ZUTDBGMG(const char *msg) { IO_CTRL *sysprintIoc = open_output_assert("ZOWEXDBG", 132, 132, dcbrecf + dcbrecbr); char writeBuf[132] = {0}; - memset(writeBuf, ' ', sizeof(132)); - int len = snprintf(writeBuf, 132, "%s", msg); + memset(writeBuf, ' ', sizeof(writeBuf)); + sprintf(writeBuf, "%.131s", msg); write_sync(sysprintIoc, writeBuf); close_assert(sysprintIoc); @@ -393,7 +399,7 @@ int ZUTSSIQ(ZDIAG *diag, JQRY_HEADER **area, const char *filter) rc = iefssi_query(&area31, &rsn, filter); if (0 != rc) { - diag->e_msg_len = sprintf(diag->e_msg, "IEFSSI_QUERY rc was: '%d', RSN was: '%d'", rc, rsn); + ZDIAG_SET_MSG(diag, "IEFSSI_QUERY rc was: '%d', RSN was: '%d'", rc, rsn); diag->detail_rc = ZUT_RTNCD_SERVICE_FAILURE; return RTNCD_FAILURE; } diff --git a/native/c/zutm31.c b/native/c/zutm31.c index 7618b3c3a..1ae9146d0 100644 --- a/native/c/zutm31.c +++ b/native/c/zutm31.c @@ -132,7 +132,7 @@ int zutm1lpl(ZDIAG *diag, int *num_dsns, PARMLIB_DSNS *dsns) if (0 != rc) { - diag->e_msg_len = sprintf(diag->e_msg, "Error: could not list parmlibs rc: '%d' rsn: '%d'", rc, rsn); + ZDIAG_SET_MSG(diag, "Error: could not list parmlibs rc: '%d' rsn: '%d'", rc, rsn); return rc; }