Skip to content

A name resolution problem about EVP_PKEY_id #1975

Closed
@bvanjoi

Description

@bvanjoi

Background

We were attempting to fix a name resolution bug in rustc on rust-lang/rust#112743. During our regression testing, we discovered an issue with rust-openssl. In this post, I'll describe the bug and explore potential solutions.

Error log

[INFO] [stderr]    Compiling openssl-macros v0.1.1
[INFO] [stdout] error[E0425]: cannot find function, tuple struct or tuple variant `EVP_PKEY_id` in crate `ffi`
[INFO] [stdout]    --> src/pkey.rs:195:36
[INFO] [stdout]     |
[INFO] [stdout] 195 |         unsafe { Id::from_raw(ffi::EVP_PKEY_id(self.as_ptr())) }
[INFO] [stdout]     |                                    ^^^^^^^^^^^ help: a constant with a similar name exists: `EVP_PKEY_DH`
[INFO] [stdout]     |
[INFO] [stdout]    ::: /opt/rustwide/cargo-home/registry/src/index.crates.io-6f17d22bba15001f/openssl-sys-0.9.88/src/./evp.rs:11:1
[INFO] [stdout]     |
[INFO] [stdout] 11  | pub const EVP_PKEY_DH: c_int = NID_dhKeyAgreement;
[INFO] [stdout]     | ---------------------------- similarly named constant `EVP_PKEY_DH` defined here

More details: rust-lang/rust#112743 (comment)

Reduced

macro_rules! cfg_if {
  ($(
      if #[cfg($($meta:meta),*)] { $($it:item)* }
  ) else * else {
      $($it2:item)*
  }) => {
      cfg_if! {
          @__items
          () ;
          $( ( ($($meta),*) ($($it)*) ), )*
          ( () ($($it2)*) ),
      }
  };

  (
      if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
      $(
          else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
      )*
  ) => {
      cfg_if! {
          @__items
          () ;
          ( ($($i_met),*) ($($i_it)*) ),
          $( ( ($($e_met),*) ($($e_it)*) ), )*
          ( () () ),
      }
  };

  (@__items ($($not:meta,)*) ; ) => {};
  (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
      cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }

      cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
  };

  (@__apply $m:meta, $($it:item)*) => {
      $(#[$m] $it)*
  };
}

mod openssl {
    pub use self::evp::*;
    pub use self::handwritten::*;

    mod evp {
        cfg_if! {
            if #[cfg(ossl300)] {
                pub unsafe fn EVP_PKEY_id() {}
            }
        }
    }

    mod handwritten {
        pub use self::evp::*;

        mod evp {
            cfg_if! {
                if #[cfg(ossl300)]  {
                    pub unsafe fn EVP_PKEY_id() {}
                } else {
                    extern "C" {
                        pub fn EVP_PKEY_id();
                    }
                }
            }
        }
    }
}

pub use openssl::*;

fn main() {
    unsafe {
        EVP_PKEY_id();
    }
}

Actually, when we compile using rustc code.rs --cfg ossl300, we expect to see an ambiguous error related to EVP_PKEY_id. However, this error is not currently being thrown. Instead, the result indicates that EVP_PKEY_id is referring to openssl::evp::EVP_PKEY_id.

btw, if you remove the cfg_if, you will encounter an ambiguous error:

mod openssl {
    pub use self::evp::*;
    pub use self::handwritten::*;

    mod evp {
        #[cfg(all(ossl300, not(any())))]
        pub unsafe fn EVP_PKEY_id() {}
    }

    mod handwritten {
        pub use self::evp::*;

        mod evp {
            #[cfg(all(ossl300, not(any())))]
            pub unsafe fn EVP_PKEY_id() {}

            #[cfg(all(not(any(ossl300))))]
            extern "C" {
                pub fn EVP_PKEY_id();
            }
        }
    }
}
pub use openssl::*;

fn main() {
    unsafe {
        EVP_PKEY_id(); //  `EVP_PKEY_id` is ambiguous
    }
}

Expected

Since I'm not familiar with this project, I'm not entirely certain how to fix this issue correctly. One possible solution is to remove the pub keyword from pub unsafe fn EVP_PKEY_id() {} in handwritten::evp, or to rename it. In any case, I believe we can resolve this problem and release a new version once it's fixed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions