diff --git a/distrib/sets/lists/comp/md.amd64 b/distrib/sets/lists/comp/md.amd64 index 55475db23..2beb2d4d7 100644 --- a/distrib/sets/lists/comp/md.amd64 +++ b/distrib/sets/lists/comp/md.amd64 @@ -1,7 +1,5 @@ -./usr/bin/addr2line ./usr/bin/as ./usr/bin/gdb -./usr/bin/readelf ./usr/include/amd64 ./usr/include/amd64/_float.h ./usr/include/amd64/_types.h @@ -80,10 +78,8 @@ ./usr/include/amd64/vga_post.h ./usr/include/amd64/vmmvar.h ./usr/include/amd64/vmparam.h -./usr/include/ieeefp.h ./usr/lib/libamd64.a ./usr/lib/libamd64_p.a -./usr/libdata/ldscripts ./usr/libdata/ldscripts/elf_i386.x ./usr/libdata/ldscripts/elf_i386.xbn ./usr/libdata/ldscripts/elf_i386.xc @@ -134,7 +130,6 @@ ./usr/libdata/ldscripts/elf_x86_64_obsd.xz ./usr/share/info/annotate.info ./usr/share/info/as.info -./usr/share/info/bfd.info ./usr/share/info/gdb.info ./usr/share/info/gdbint.info ./usr/share/info/ld.info diff --git a/distrib/sets/lists/comp/md.arm64 b/distrib/sets/lists/comp/md.arm64 index 34e82a704..f5161bdc0 100644 --- a/distrib/sets/lists/comp/md.arm64 +++ b/distrib/sets/lists/comp/md.arm64 @@ -1,5 +1,3 @@ -./usr/bin/addr2line -./usr/bin/readelf ./usr/include/arm64 ./usr/include/arm64/_float.h ./usr/include/arm64/_types.h @@ -56,6 +54,3 @@ ./usr/include/arm64/trap.h ./usr/include/arm64/vmmvar.h ./usr/include/arm64/vmparam.h -./usr/include/ieeefp.h -./usr/libdata/ldscripts -./usr/share/info/bfd.info diff --git a/distrib/sets/lists/comp/md.armv7 b/distrib/sets/lists/comp/md.armv7 index 0fee78f66..aad2f5316 100644 --- a/distrib/sets/lists/comp/md.armv7 +++ b/distrib/sets/lists/comp/md.armv7 @@ -1,7 +1,5 @@ -./usr/bin/addr2line ./usr/bin/as ./usr/bin/gdb -./usr/bin/readelf ./usr/include/arm ./usr/include/arm/_float.h ./usr/include/arm/_types.h @@ -101,10 +99,8 @@ ./usr/include/armv7/timetc.h ./usr/include/armv7/trap.h ./usr/include/armv7/vmparam.h -./usr/include/ieeefp.h ./usr/lib/libarm.a ./usr/lib/libarm_p.a -./usr/libdata/ldscripts ./usr/libdata/ldscripts/armelf_obsd.x ./usr/libdata/ldscripts/armelf_obsd.xbn ./usr/libdata/ldscripts/armelf_obsd.xc @@ -139,7 +135,6 @@ ./usr/libdata/ldscripts/armelfb_obsd.xz ./usr/share/info/annotate.info ./usr/share/info/as.info -./usr/share/info/bfd.info ./usr/share/info/gdb.info ./usr/share/info/gdbint.info ./usr/share/info/ld.info diff --git a/distrib/sets/lists/comp/md.i386 b/distrib/sets/lists/comp/md.i386 index 26289ead5..2dc5c40f7 100644 --- a/distrib/sets/lists/comp/md.i386 +++ b/distrib/sets/lists/comp/md.i386 @@ -1,7 +1,5 @@ -./usr/bin/addr2line ./usr/bin/as ./usr/bin/gdb -./usr/bin/readelf ./usr/include/i386 ./usr/include/i386/_float.h ./usr/include/i386/_types.h @@ -78,10 +76,8 @@ ./usr/include/i386/vga_post.h ./usr/include/i386/vmmvar.h ./usr/include/i386/vmparam.h -./usr/include/ieeefp.h ./usr/lib/libi386.a ./usr/lib/libi386_p.a -./usr/libdata/ldscripts ./usr/libdata/ldscripts/elf_i386_obsd.x ./usr/libdata/ldscripts/elf_i386_obsd.xbn ./usr/libdata/ldscripts/elf_i386_obsd.xc @@ -100,7 +96,6 @@ ./usr/libdata/ldscripts/elf_i386_obsd.xz ./usr/share/info/annotate.info ./usr/share/info/as.info -./usr/share/info/bfd.info ./usr/share/info/gdb.info ./usr/share/info/gdbint.info ./usr/share/info/ld.info diff --git a/distrib/sets/lists/comp/mi b/distrib/sets/lists/comp/mi index 52b2b0328..e06fb3a7d 100644 --- a/distrib/sets/lists/comp/mi +++ b/distrib/sets/lists/comp/mi @@ -1,4 +1,5 @@ ./sys +./usr/bin/addr2line ./usr/bin/c++filt ./usr/bin/cpp ./usr/bin/ctfdump @@ -10,6 +11,7 @@ ./usr/bin/lorder ./usr/bin/objdump ./usr/bin/ranlib +./usr/bin/readelf ./usr/bin/rpcgen ./usr/bin/yacc ./usr/include/FlexLexer.h @@ -919,6 +921,7 @@ ./usr/include/grp.h ./usr/include/histedit.h ./usr/include/icdb.h +./usr/include/ieeefp.h ./usr/include/ifaddrs.h ./usr/include/imsg.h ./usr/include/inttypes.h @@ -1579,7 +1582,9 @@ ./usr/lib/liby_p.a ./usr/lib/libz.a ./usr/lib/libz_p.a +./usr/libdata/ldscripts ./usr/sbin/kgmon +./usr/share/info/bfd.info ./usr/share/info/binutils.info ./usr/share/man/man1/addr2line.1 ./usr/share/man/man1/ar.1 diff --git a/regress/lib/libssl/tlsfuzzer/tlsfuzzer.py b/regress/lib/libssl/tlsfuzzer/tlsfuzzer.py index 404cb2d89..91aedad16 100644 --- a/regress/lib/libssl/tlsfuzzer/tlsfuzzer.py +++ b/regress/lib/libssl/tlsfuzzer/tlsfuzzer.py @@ -1,4 +1,4 @@ -# $OpenBSD: tlsfuzzer.py,v 1.55 2024/09/14 07:11:34 tb Exp $ +# $OpenBSD: tlsfuzzer.py,v 1.56 2024/09/18 19:12:37 tb Exp $ # # Copyright (c) 2020 Theo Buehler # @@ -211,10 +211,9 @@ tls13_slow_tests = TestGroup("slow TLSv1.3 tests", [ ]), # We don't accept an empty ECPF extension since it must advertise the # uncompressed point format. Exclude this extension type from the test. - # Also exclude QUIC transport parameters. Test( "test-tls13-large-number-of-extensions.py", - tls13_args = ["--exc", "11", "--exc", "57"], + tls13_args = ["--exc", "11"], ), ]) @@ -365,6 +364,7 @@ tls12_tests = TestGroup("TLSv1.2 tests", [ Test("test-invalid-content-type.py"), Test("test-invalid-session-id.py"), Test("test-invalid-version.py"), + Test("test-large-number-of-extensions.py"), Test("test-lucky13.py"), Test("test-message-skipping.py"), Test("test-no-heartbeat.py"), @@ -533,11 +533,6 @@ tls12_failing_tests = TestGroup("failing TLSv1.2 tests", [ # again illegal_parameter vs unrecognized_name Test("test-invalid-server-name-extension.py"), - # 14 pass - # 7 fail - # 'n extensions', n in 4095, 4096, 4097, 8191, 8192, 8193, 16383, - Test("test-large-number-of-extensions.py"), - # 4 failures: # 'insecure (legacy) renegotiation with GET after 2nd handshake' # 'insecure (legacy) renegotiation with incomplete GET' diff --git a/sys/dev/pci/drm/amd/amdgpu/jpeg_v1_0.c b/sys/dev/pci/drm/amd/amdgpu/jpeg_v1_0.c index eb9e8a4ce..66d01af4c 100644 --- a/sys/dev/pci/drm/amd/amdgpu/jpeg_v1_0.c +++ b/sys/dev/pci/drm/amd/amdgpu/jpeg_v1_0.c @@ -23,6 +23,7 @@ #include "amdgpu.h" #include "amdgpu_jpeg.h" +#include "amdgpu_cs.h" #include "soc15.h" #include "soc15d.h" #include "vcn_v1_0.h" @@ -34,6 +35,9 @@ static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev); static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev); static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring); +static int jpeg_v1_dec_ring_parse_cs(struct amdgpu_cs_parser *parser, + struct amdgpu_job *job, + struct amdgpu_ib *ib); static void jpeg_v1_0_decode_ring_patch_wreg(struct amdgpu_ring *ring, uint32_t *ptr, uint32_t reg_offset, uint32_t val) { @@ -300,7 +304,10 @@ static void jpeg_v1_0_decode_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_VMID), 0, 0, PACKETJ_TYPE0)); - amdgpu_ring_write(ring, (vmid | (vmid << 4))); + if (ring->funcs->parse_cs) + amdgpu_ring_write(ring, 0); + else + amdgpu_ring_write(ring, (vmid | (vmid << 4))); amdgpu_ring_write(ring, PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JPEG_VMID), 0, 0, PACKETJ_TYPE0)); @@ -554,6 +561,7 @@ static const struct amdgpu_ring_funcs jpeg_v1_0_decode_ring_vm_funcs = { .get_rptr = jpeg_v1_0_decode_ring_get_rptr, .get_wptr = jpeg_v1_0_decode_ring_get_wptr, .set_wptr = jpeg_v1_0_decode_ring_set_wptr, + .parse_cs = jpeg_v1_dec_ring_parse_cs, .emit_frame_size = 6 + 6 + /* hdp invalidate / flush */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + @@ -612,3 +620,69 @@ static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring) vcn_v1_0_set_pg_for_begin_use(ring, set_clocks); } + +/** + * jpeg_v1_dec_ring_parse_cs - command submission parser + * + * @parser: Command submission parser context + * @job: the job to parse + * @ib: the IB to parse + * + * Parse the command stream, return -EINVAL for invalid packet, + * 0 otherwise + */ +static int jpeg_v1_dec_ring_parse_cs(struct amdgpu_cs_parser *parser, + struct amdgpu_job *job, + struct amdgpu_ib *ib) +{ + u32 i, reg, res, cond, type; + int ret = 0; + struct amdgpu_device *adev = parser->adev; + + for (i = 0; i < ib->length_dw ; i += 2) { + reg = CP_PACKETJ_GET_REG(ib->ptr[i]); + res = CP_PACKETJ_GET_RES(ib->ptr[i]); + cond = CP_PACKETJ_GET_COND(ib->ptr[i]); + type = CP_PACKETJ_GET_TYPE(ib->ptr[i]); + + if (res || cond != PACKETJ_CONDITION_CHECK0) /* only allow 0 for now */ + return -EINVAL; + + if (reg >= JPEG_V1_REG_RANGE_START && reg <= JPEG_V1_REG_RANGE_END) + continue; + + switch (type) { + case PACKETJ_TYPE0: + if (reg != JPEG_V1_LMI_JPEG_WRITE_64BIT_BAR_HIGH && + reg != JPEG_V1_LMI_JPEG_WRITE_64BIT_BAR_LOW && + reg != JPEG_V1_LMI_JPEG_READ_64BIT_BAR_HIGH && + reg != JPEG_V1_LMI_JPEG_READ_64BIT_BAR_LOW && + reg != JPEG_V1_REG_CTX_INDEX && + reg != JPEG_V1_REG_CTX_DATA) { + ret = -EINVAL; + } + break; + case PACKETJ_TYPE1: + if (reg != JPEG_V1_REG_CTX_DATA) + ret = -EINVAL; + break; + case PACKETJ_TYPE3: + if (reg != JPEG_V1_REG_SOFT_RESET) + ret = -EINVAL; + break; + case PACKETJ_TYPE6: + if (ib->ptr[i] != CP_PACKETJ_NOP) + ret = -EINVAL; + break; + default: + ret = -EINVAL; + } + + if (ret) { + dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]); + break; + } + } + + return ret; +} diff --git a/sys/dev/pci/drm/amd/amdgpu/jpeg_v1_0.h b/sys/dev/pci/drm/amd/amdgpu/jpeg_v1_0.h index bbf33a6a3..9654d22e0 100644 --- a/sys/dev/pci/drm/amd/amdgpu/jpeg_v1_0.h +++ b/sys/dev/pci/drm/amd/amdgpu/jpeg_v1_0.h @@ -29,4 +29,15 @@ int jpeg_v1_0_sw_init(void *handle); void jpeg_v1_0_sw_fini(void *handle); void jpeg_v1_0_start(struct amdgpu_device *adev, int mode); +#define JPEG_V1_REG_RANGE_START 0x8000 +#define JPEG_V1_REG_RANGE_END 0x803f + +#define JPEG_V1_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x8238 +#define JPEG_V1_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x8239 +#define JPEG_V1_LMI_JPEG_READ_64BIT_BAR_HIGH 0x825a +#define JPEG_V1_LMI_JPEG_READ_64BIT_BAR_LOW 0x825b +#define JPEG_V1_REG_CTX_INDEX 0x8328 +#define JPEG_V1_REG_CTX_DATA 0x8329 +#define JPEG_V1_REG_SOFT_RESET 0x83a0 + #endif /*__JPEG_V1_0_H__*/ diff --git a/sys/dev/pci/drm/amd/display/dc/link/protocols/link_dp_phy.c b/sys/dev/pci/drm/amd/display/dc/link/protocols/link_dp_phy.c index 4db876277..ac8d39993 100644 --- a/sys/dev/pci/drm/amd/display/dc/link/protocols/link_dp_phy.c +++ b/sys/dev/pci/drm/amd/display/dc/link/protocols/link_dp_phy.c @@ -143,32 +143,25 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); + if (link_enc->funcs->fec_set_ready == NULL) + return DC_NOT_SUPPORTED; - if (!dp_should_enable_fec(link)) - return status; + if (ready && dp_should_enable_fec(link)) { + fec_config = 1; - if (link_enc->funcs->fec_set_ready && - link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) { - if (ready) { - fec_config = 1; - status = core_link_write_dpcd(link, - DP_FEC_CONFIGURATION, - &fec_config, - sizeof(fec_config)); - if (status == DC_OK) { - link_enc->funcs->fec_set_ready(link_enc, true); - link->fec_state = dc_link_fec_ready; - } else { - link_enc->funcs->fec_set_ready(link_enc, false); - link->fec_state = dc_link_fec_not_ready; - dm_error("dpcd write failed to set fec_ready"); - } - } else if (link->fec_state == dc_link_fec_ready) { + status = core_link_write_dpcd(link, DP_FEC_CONFIGURATION, + &fec_config, sizeof(fec_config)); + + if (status == DC_OK) { + link_enc->funcs->fec_set_ready(link_enc, true); + link->fec_state = dc_link_fec_ready; + } + } else { + if (link->fec_state == dc_link_fec_ready) { fec_config = 0; - status = core_link_write_dpcd(link, - DP_FEC_CONFIGURATION, - &fec_config, - sizeof(fec_config)); + core_link_write_dpcd(link, DP_FEC_CONFIGURATION, + &fec_config, sizeof(fec_config)); + link_enc->funcs->fec_set_ready(link_enc, false); link->fec_state = dc_link_fec_not_ready; } @@ -183,14 +176,12 @@ void dp_set_fec_enable(struct dc_link *link, bool enable) link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); - - if (!dp_should_enable_fec(link)) + if (link_enc->funcs->fec_set_enable == NULL) return; - if (link_enc->funcs->fec_set_enable && - link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) { - if (link->fec_state == dc_link_fec_ready && enable) { - /* Accord to DP spec, FEC enable sequence can first + if (enable && dp_should_enable_fec(link)) { + if (link->fec_state == dc_link_fec_ready) { + /* According to DP spec, FEC enable sequence can first * be transmitted anytime after 1000 LL codes have * been transmitted on the link after link training * completion. Using 1 lane RBR should have the maximum @@ -200,7 +191,9 @@ void dp_set_fec_enable(struct dc_link *link, bool enable) udelay(7); link_enc->funcs->fec_set_enable(link_enc, true); link->fec_state = dc_link_fec_enabled; - } else if (link->fec_state == dc_link_fec_enabled && !enable) { + } + } else { + if (link->fec_state == dc_link_fec_enabled) { link_enc->funcs->fec_set_enable(link_enc, false); link->fec_state = dc_link_fec_ready; } diff --git a/sys/dev/pci/drm/amd/include/atomfirmware.h b/sys/dev/pci/drm/amd/include/atomfirmware.h index 8a1702ff6..1a3b98d7c 100644 --- a/sys/dev/pci/drm/amd/include/atomfirmware.h +++ b/sys/dev/pci/drm/amd/include/atomfirmware.h @@ -1006,7 +1006,7 @@ struct display_object_info_table_v1_4 uint16_t supporteddevices; uint8_t number_of_path; uint8_t reserved; - struct atom_display_object_path_v2 display_path[8]; //the real number of this included in the structure is calculated by using the (whole structure size - the header size- number_of_path)/size of atom_display_object_path + struct atom_display_object_path_v2 display_path[]; //the real number of this included in the structure is calculated by using the (whole structure size - the header size- number_of_path)/size of atom_display_object_path }; struct display_object_info_table_v1_5 { @@ -1016,7 +1016,7 @@ struct display_object_info_table_v1_5 { uint8_t reserved; // the real number of this included in the structure is calculated by using the // (whole structure size - the header size- number_of_path)/size of atom_display_object_path - struct atom_display_object_path_v3 display_path[8]; + struct atom_display_object_path_v3 display_path[]; }; /* diff --git a/sys/dev/pci/drm/drm_panel_orientation_quirks.c b/sys/dev/pci/drm/drm_panel_orientation_quirks.c index 267f3f517..a9e561cdd 100644 --- a/sys/dev/pci/drm/drm_panel_orientation_quirks.c +++ b/sys/dev/pci/drm/drm_panel_orientation_quirks.c @@ -208,6 +208,18 @@ static const struct dmi_system_id orientation_data[] = { DMI_MATCH(DMI_BOARD_NAME, "KUN"), }, .driver_data = (void *)&lcd1600x2560_rightside_up, + }, { /* AYN Loki Max */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ayn"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Loki Max"), + }, + .driver_data = (void *)&lcd1080x1920_leftside_up, + }, { /* AYN Loki Zero */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ayn"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Loki Zero"), + }, + .driver_data = (void *)&lcd1080x1920_leftside_up, }, { /* Chuwi HiBook (CWI514) */ .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), diff --git a/sys/dev/pci/drm/drm_syncobj.c b/sys/dev/pci/drm/drm_syncobj.c index 841bc9081..8a5c553ae 100644 --- a/sys/dev/pci/drm/drm_syncobj.c +++ b/sys/dev/pci/drm/drm_syncobj.c @@ -1489,6 +1489,7 @@ drm_syncobj_eventfd_ioctl(struct drm_device *dev, void *data, struct drm_syncobj *syncobj; struct eventfd_ctx *ev_fd_ctx; struct syncobj_eventfd_entry *entry; + int ret; if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) return -EOPNOTSUPP; @@ -1504,13 +1505,15 @@ drm_syncobj_eventfd_ioctl(struct drm_device *dev, void *data, return -ENOENT; ev_fd_ctx = eventfd_ctx_fdget(args->fd); - if (IS_ERR(ev_fd_ctx)) - return PTR_ERR(ev_fd_ctx); + if (IS_ERR(ev_fd_ctx)) { + ret = PTR_ERR(ev_fd_ctx); + goto err_fdget; + } entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (!entry) { - eventfd_ctx_put(ev_fd_ctx); - return -ENOMEM; + ret = -ENOMEM; + goto err_kzalloc; } entry->syncobj = syncobj; entry->ev_fd_ctx = ev_fd_ctx; @@ -1521,6 +1524,12 @@ drm_syncobj_eventfd_ioctl(struct drm_device *dev, void *data, drm_syncobj_put(syncobj); return 0; + +err_kzalloc: + eventfd_ctx_put(ev_fd_ctx); +err_fdget: + drm_syncobj_put(syncobj); + return ret; #endif } diff --git a/sys/dev/pci/drm/i915/gt/uc/intel_guc_submission.c b/sys/dev/pci/drm/i915/gt/uc/intel_guc_submission.c index 2c9de9a67..875dfa553 100644 --- a/sys/dev/pci/drm/i915/gt/uc/intel_guc_submission.c +++ b/sys/dev/pci/drm/i915/gt/uc/intel_guc_submission.c @@ -2695,9 +2695,9 @@ static void prepare_context_registration_info_v70(struct intel_context *ce, ce->parallel.guc.wqi_tail = 0; ce->parallel.guc.wqi_head = 0; - wq_desc_offset = i915_ggtt_offset(ce->state) + + wq_desc_offset = (u64)i915_ggtt_offset(ce->state) + __get_parent_scratch_offset(ce); - wq_base_offset = i915_ggtt_offset(ce->state) + + wq_base_offset = (u64)i915_ggtt_offset(ce->state) + __get_wq_offset(ce); info->wq_desc_lo = lower_32_bits(wq_desc_offset); info->wq_desc_hi = upper_32_bits(wq_desc_offset); diff --git a/usr.sbin/zic/zic.8 b/usr.sbin/zic/zic.8 index 0ed93b541..4b0ebdf23 100644 --- a/usr.sbin/zic/zic.8 +++ b/usr.sbin/zic/zic.8 @@ -1,5 +1,5 @@ -.\" $OpenBSD: zic.8,v 1.5 2022/03/31 17:27:32 naddy Exp $ -.Dd $Mdocdate: March 31 2022 $ +.\" $OpenBSD: zic.8,v 1.6 2024/09/18 17:05:50 millert Exp $ +.Dd $Mdocdate: September 18 2024 $ .Dt ZIC 8 .Os .Sh NAME @@ -240,6 +240,19 @@ The pair of characters is used to show where the .Dq variable part of the time zone abbreviation goes. +Alternately, a format can use the pair of characters +.Em %z +to stand for the UTC offset in the form +.No \(+- Ns Em hh , +.No \(+- Ns Em hhmm , +or +.No \(+- Ns Em hhmmss , +using the shortest form that does not lose information, where +.Em hh , +.Em mm , +and +.Em ss +are the hours, minutes, and seconds east (+) or west (\(mi) of UTC. Alternately, a slash .Pq \&/ diff --git a/usr.sbin/zic/zic.c b/usr.sbin/zic/zic.c index 420b75f82..2f94cd737 100644 --- a/usr.sbin/zic/zic.c +++ b/usr.sbin/zic/zic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: zic.c,v 1.26 2020/10/13 00:18:46 deraadt Exp $ */ +/* $OpenBSD: zic.c,v 1.27 2024/09/18 17:05:50 millert Exp $ */ /* ** This file is in the public domain, so clarified as of ** 2006-07-17 by Arthur David Olson. @@ -88,6 +88,7 @@ struct zone { long z_gmtoff; const char *z_rule; const char *z_format; + char z_format_specifier; long z_stdoff; @@ -107,7 +108,7 @@ static void associate(void); static void convert(long val, char *buf); static void convert64(zic_t val, char *buf); static void dolink(const char *fromfield, const char *tofield); -static void doabbr(char *abbr, size_t size, const char *format, +static void doabbr(char *abbr, size_t size, struct zone const *zp, const char *letters, int isdst, int doquotes); static void eat(const char *name, int num); static void eats(const char *name, int num, const char *rname, int rnum); @@ -148,6 +149,9 @@ static void writezone(const char *name, const char *string); extern char *__progname; +/* Bound on length of what %z can expand to. */ +enum { PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1 }; + static int charcnt; static int errors; static const char *filename; @@ -156,7 +160,7 @@ static int leapseen; static int leapminyear; static int leapmaxyear; static int linenum; -static int max_abbrvar_len; +static int max_abbrvar_len = PERCENT_Z_LEN_BOUND; static int max_format_len; static zic_t max_time; static int max_year; @@ -739,7 +743,7 @@ associate(void) ** Note, though, that if there's no rule, ** a '%s' in the format is a bad thing. */ - if (strchr(zp->z_format, '%') != 0) + if (zp->z_format_specifier == 's') error("%s in ruleless zone"); } } @@ -957,6 +961,7 @@ static int inzsub(char **fields, int nfields, int iscont) { char *cp; + char *cp1; static struct zone z; int i_gmtoff, i_rule, i_format; int i_untilyear, i_untilmonth; @@ -986,13 +991,22 @@ inzsub(char **fields, int nfields, int iscont) z.z_linenum = linenum; z.z_gmtoff = gethms(fields[i_gmtoff], "invalid UTC offset", TRUE); if ((cp = strchr(fields[i_format], '%')) != 0) { - if (*++cp != 's' || strchr(cp, '%') != 0) { + if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%') + || strchr(fields[i_format], '/')) { error("invalid abbreviation format"); return FALSE; } } z.z_rule = ecpyalloc(fields[i_rule]); - z.z_format = ecpyalloc(fields[i_format]); + z.z_format = cp1 = ecpyalloc(fields[i_format]); + z.z_format_specifier = cp ? *cp : '\0'; + if (z.z_format_specifier == 'z') { + if (noise) { + warning("format '%%z' not handled by pre-2015 versions " + "of zic"); + } + cp1[cp - fields[i_format]] = 's'; + } if (max_format_len < strlen(z.z_format)) max_format_len = strlen(z.z_format); hasuntil = nfields > i_untilyear; @@ -1635,19 +1649,58 @@ writezone(const char *name, const char *string) errx(1, "Error writing %s", fullname); } +static char const * +abbroffset(char *buf, zic_t offset) +{ + char sign = '+'; + int seconds, minutes; + + if (offset < 0) { + offset = -offset; + sign = '-'; + } + + seconds = offset % SECSPERMIN; + offset /= SECSPERMIN; + minutes = offset % MINSPERHOUR; + offset /= MINSPERHOUR; + if (100 <= offset) { + error("%%z UTC offset magnitude exceeds 99:59:59"); + return "%z"; + } else { + char *p = buf; + *p++ = sign; + *p++ = '0' + offset / 10; + *p++ = '0' + offset % 10; + if (minutes | seconds) { + *p++ = '0' + minutes / 10; + *p++ = '0' + minutes % 10; + if (seconds) { + *p++ = '0' + seconds / 10; + *p++ = '0' + seconds % 10; + } + } + *p = '\0'; + return buf; + } +} + static void -doabbr(char *abbr, size_t size, const char *format, const char *letters, +doabbr(char *abbr, size_t size, struct zone const *zp, const char *letters, int isdst, int doquotes) { char *cp, *slashp; - int len; + size_t len; + char const *format = zp->z_format; slashp = strchr(format, '/'); if (slashp == NULL) { - if (letters == NULL) - strlcpy(abbr, format, size); - else - snprintf(abbr, size, format, letters); + char letterbuf[PERCENT_Z_LEN_BOUND + 1]; + if (zp->z_format_specifier == 'z') + letters = abbroffset(letterbuf, -zp->z_gmtoff); + else if (letters == NULL) + letters = "%s"; + snprintf(abbr, size, format, letters); } else if (isdst) { strlcpy(abbr, slashp + 1, size); } else { @@ -1822,7 +1875,7 @@ stringzone(char *result, size_t size, const struct zone *zpfirst, int zonecount) if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_stdoff != 0)) return; abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; - doabbr(result, size, zp->z_format, abbrvar, FALSE, TRUE); + doabbr(result, size, zp, abbrvar, FALSE, TRUE); ep = end(result, size); if (stringoffset(ep, size - (ep - result), -zp->z_gmtoff) != 0) { result[0] = '\0'; @@ -1831,7 +1884,7 @@ stringzone(char *result, size_t size, const struct zone *zpfirst, int zonecount) if (dstrp == NULL) return; ep = end(result, size); - doabbr(ep, size - (ep - result), zp->z_format, dstrp->r_abbrvar, TRUE, TRUE); + doabbr(ep, size - (ep - result), zp, dstrp->r_abbrvar, TRUE, TRUE); if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) { ep = end(result, size); if (stringoffset(ep, size - (ep - result), @@ -1957,8 +2010,8 @@ outzone(const struct zone *zpfirst, int zonecount) startoff = zp->z_gmtoff; if (zp->z_nrules == 0) { stdoff = zp->z_stdoff; - doabbr(startbuf, max_abbr_len + 1, zp->z_format, - NULL, stdoff != 0, FALSE); + doabbr(startbuf, max_abbr_len + 1, zp, NULL, + stdoff != 0, FALSE); type = addtype(oadd(zp->z_gmtoff, stdoff), startbuf, stdoff != 0, startttisstd, startttisgmt); @@ -2041,7 +2094,7 @@ outzone(const struct zone *zpfirst, int zonecount) stdoff); doabbr(startbuf, max_abbr_len + 1, - zp->z_format, + zp, rp->r_abbrvar, rp->r_stdoff != 0, FALSE); @@ -2052,7 +2105,7 @@ outzone(const struct zone *zpfirst, int zonecount) stdoff)) { doabbr(startbuf, max_abbr_len + 1, - zp->z_format, + zp, rp->r_abbrvar, rp->r_stdoff != 0, FALSE); @@ -2060,7 +2113,7 @@ outzone(const struct zone *zpfirst, int zonecount) } eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); - doabbr(ab, max_abbr_len + 1, zp->z_format, + doabbr(ab, max_abbr_len + 1, zp, rp->r_abbrvar, rp->r_stdoff != 0, FALSE); offset = oadd(zp->z_gmtoff, rp->r_stdoff); type = addtype(offset, ab, rp->r_stdoff != 0,