@@ -33,6 +33,7 @@ pub mod shared_zone;
33
33
pub mod ssl;
34
34
35
35
const NGX_CONF_DUPLICATE : * mut c_char = c"is duplicate" . as_ptr ( ) . cast_mut ( ) ;
36
+ const NGX_CONF_INVALID_VALUE : * mut c_char = c"invalid value" . as_ptr ( ) . cast_mut ( ) ;
36
37
37
38
/// Main (http block) level configuration.
38
39
#[ derive( Debug , Default ) ]
@@ -337,12 +338,12 @@ extern "C" fn cmd_issuer_add_contact(
337
338
// NGX_CONF_TAKE1 ensures that args contains 2 elements
338
339
let args = cf. args ( ) ;
339
340
340
- if args[ 1 ] . is_empty ( ) || core :: str :: from_utf8 ( args [ 1 ] . as_bytes ( ) ) . is_err ( ) {
341
- return c"invalid value" . as_ptr ( ) . cast_mut ( ) ;
341
+ if args[ 1 ] . is_empty ( ) {
342
+ return NGX_CONF_INVALID_VALUE ;
342
343
} ;
343
344
344
- if has_scheme ( args[ 1 ] . as_ref ( ) ) {
345
- issuer . contacts . push ( args[ 1 ] ) ;
345
+ let value = if has_scheme ( args[ 1 ] . as_ref ( ) ) {
346
+ args[ 1 ]
346
347
} else {
347
348
let mut value = ngx_str_t:: empty ( ) ;
348
349
value. len = MAILTO . len ( ) + args[ 1 ] . len ;
@@ -353,11 +354,18 @@ extern "C" fn cmd_issuer_add_contact(
353
354
354
355
value. as_bytes_mut ( ) [ ..MAILTO . len ( ) ] . copy_from_slice ( MAILTO ) ;
355
356
value. as_bytes_mut ( ) [ MAILTO . len ( ) ..] . copy_from_slice ( args[ 1 ] . as_ref ( ) ) ;
357
+ value
358
+ } ;
356
359
357
- issuer. contacts . push ( value) ;
360
+ // SAFETY: the value is not empty, well aligned, and the conversion result is assigned to an
361
+ // object in the same pool.
362
+ match unsafe { conf_value_to_str ( & value) } {
363
+ Ok ( x) => {
364
+ issuer. contacts . push ( x) ;
365
+ NGX_CONF_OK
366
+ }
367
+ Err ( _) => NGX_CONF_INVALID_VALUE ,
358
368
}
359
-
360
- NGX_CONF_OK
361
369
}
362
370
363
371
extern "C" fn cmd_issuer_set_account_key (
@@ -566,3 +574,26 @@ fn conf_check_nargs(cmd: &ngx_command_t, nargs: ngx_uint_t) -> bool {
566
574
nargs <= ARGUMENT_NUMBER . len ( ) && ( flags & ARGUMENT_NUMBER [ nargs - 1 ] ) != 0
567
575
}
568
576
}
577
+
578
+ /// Unsafely converts `ngx_str_t` into a static UTF-8 string reference.
579
+ ///
580
+ /// # Safety
581
+ ///
582
+ /// `value` must be allocated on the configuration (cycle) pool, and stored in another object on the
583
+ /// same pool. With that, we can expect that both the borrowed string and the owning object will be
584
+ /// destroyed simultaneously.
585
+ ///
586
+ /// In the worker process this happens at the process exit, making the `'static` lifetime specifier
587
+ /// accurate.
588
+ /// In the master process, the cycle pool is destroyed after reloading the configuration, along with
589
+ /// all the configuration objects. But this process role is not capable of serving connections or
590
+ /// running background tasks, and thus will not create additional borrows with potentially extended
591
+ /// lifetime.
592
+ unsafe fn conf_value_to_str ( value : & ngx_str_t ) -> Result < & ' static str , core:: str:: Utf8Error > {
593
+ if value. len == 0 {
594
+ Ok ( "" )
595
+ } else {
596
+ let bytes = core:: slice:: from_raw_parts ( value. data , value. len ) ;
597
+ core:: str:: from_utf8 ( bytes)
598
+ }
599
+ }
0 commit comments