Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2543,6 +2543,16 @@ bool Converter::VisitMemberExpr(clang::MemberExpr *expr) {
return false;
}

// char* fields in libc structs are *mut i8. We represent char* as *mut u8. Do
// the i8 -> u8 conversion here.
if (IsCharPointerFieldFromLibc(member)) {
StrCat(std::format("({} as {})", str,
member->getType()->getPointeeType().isConstQualified()
? "*const u8"
: "*mut u8"));
return false;
}

StrCat(str);
return false;
}
Expand Down
10 changes: 10 additions & 0 deletions cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,16 @@ bool IsInMainFile(const clang::Decl *decl) {
return src_mgr.isInMainFile(src_mgr.getExpansionLoc(loc));
}

bool IsCharPointerFieldFromLibc(const clang::ValueDecl *decl) {
auto field = clang::dyn_cast<clang::FieldDecl>(decl);
if (!field || !field->getType()->isPointerType() ||
!field->getType()->getPointeeType()->isCharType()) {
return false;
}
return field->getASTContext().getSourceManager().isInSystemHeader(
field->getParent()->getLocation());
}

bool IsUserDefinedDecl(const clang::Decl *decl) {
const auto &ctx = decl->getASTContext();
const auto &src_mgr = ctx.getSourceManager();
Expand Down
2 changes: 2 additions & 0 deletions cpp2rust/converter/converter_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ bool IsComparisonWithNullOp(const clang::BinaryOperator *expr);

bool IsInMainFile(const clang::Decl *decl);

bool IsCharPointerFieldFromLibc(const clang::ValueDecl *decl);

bool IsUserDefinedDecl(const clang::Decl *decl);

bool RefersToUserDefinedDecl(const clang::Expr *expr);
Expand Down
12 changes: 12 additions & 0 deletions tests/unit/libc_char_ptr_field.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// no-compile: refcount
#include <pwd.h>
#include <unistd.h>

int main(void) {
struct passwd *pw = getpwuid(geteuid());
if (!pw) {
return 0;
}
char *home = pw->pw_dir;
return home == 0;
}
21 changes: 21 additions & 0 deletions tests/unit/out/unsafe/libc_char_ptr_field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
extern crate libc;
use libc::*;
extern crate libcc2rs;
use libcc2rs::*;
use std::collections::BTreeMap;
use std::io::{Read, Seek, Write};
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
use std::rc::Rc;
pub fn main() {
unsafe {
std::process::exit(main_0() as i32);
}
}
unsafe fn main_0() -> i32 {
let mut pw: *mut passwd = libc::getpwuid(libc::geteuid());
if !!(pw).is_null() {
return 0;
}
let mut home: *mut u8 = ((*pw).pw_dir as *mut u8);
return (((home).is_null()) as i32);
}
Loading