Compare commits

..

10 Commits

Author SHA1 Message Date
Kim Kulling
e73a537081 Merge branch 'master' into feature/rust_bindings 2026-04-06 16:20:25 +02:00
Kim Kulling
48515a4aa1 Merge branch 'master' into feature/rust_bindings 2026-02-26 15:33:51 +01:00
Kim Kulling
1ed019b869 Remove generated file 2026-02-26 15:29:58 +01:00
Kim Kulling
7c7a1233f5 Fix formatting in Cargo.toml 2026-02-26 15:28:14 +01:00
Kim Kulling
3e6482bca0 Update build.rs 2026-02-23 21:28:49 +01:00
Kim Kulling
c0d273cb3b Apply suggestion from @coderabbitai[bot]
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-02-23 21:28:00 +01:00
Kim Kulling
e730b7803c Add missing includes for the rust bindings. 2026-02-23 16:20:04 +01:00
Kim Kulling
cedc5a8d10 Merge branch 'master' into feature/rust_bindings 2026-02-04 11:38:57 +01:00
Kim Kulling
4d3a694807 Fix bindgen usage. 2026-02-03 21:06:25 +01:00
Kim Kulling
517fb1b242 Add files for assimp rust wrapper 2026-01-27 21:33:02 +01:00
11 changed files with 38 additions and 92 deletions

View File

@@ -89,7 +89,7 @@ jobs:
run: echo "args=-DBUILD_SHARED_LIBS=OFF -DASSIMP_HUNTER_ENABLED=ON -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/cmake/polly/${{ matrix.toolchain }}.cmake" >> $GITHUB_OUTPUT
- name: configure and build
uses: lukka/run-cmake@v10
uses: lukka/run-cmake@v3
env:
DXSDK_DIR: '${{ github.workspace }}/DX_SDK'
@@ -182,7 +182,7 @@ jobs:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- uses: softprops/action-gh-release@v3
- uses: softprops/action-gh-release@v2
with:
name: create-release
- id: upload-url
@@ -197,4 +197,4 @@ jobs:
with:
files: |
*.zip

View File

@@ -45,7 +45,7 @@ jobs:
filename: ${{ matrix.name }}-${{ github.event.release.tag_name }}.zip
directory: build/bin/
- uses: softprops/action-gh-release@v3
- uses: softprops/action-gh-release@v2
with:
files: build/bin/${{ matrix.name }}-${{ github.event.release.tag_name }}.zip
append_body: true

View File

@@ -22,7 +22,7 @@ jobs:
CC: clang
- name: configure and build
uses: lukka/run-cmake@v10
uses: lukka/run-cmake@v3
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
@@ -46,7 +46,7 @@ jobs:
CC: clang
- name: configure and build
uses: lukka/run-cmake@v10
uses: lukka/run-cmake@v3
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'

View File

@@ -507,20 +507,16 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
}
if (table && !table->mMap.empty()) {
if (matIdx < newMats.size()) {
std::pair<Collada::Effect *, aiMaterial *> &mat = newMats[matIdx];
std::pair<Collada::Effect *, aiMaterial *> &mat = newMats[matIdx];
// Iterate through all texture channels assigned to the effect and
// check whether we have mapping information for it.
ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table);
} else {
ASSIMP_LOG_WARN("Collada: Ignoring material mapping for mesh \"", mid.mMeshOrController, "\". Material index ", matIdx, " is out of bounds (newMats.size()=", newMats.size(), ").");
}
// Iterate through all texture channels assigned to the effect and
// check whether we have mapping information for it.
ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table);
}
// built lookup index of the Mesh-Submesh-Material combination

View File

@@ -90,7 +90,7 @@ namespace {
// Returns whether the class can handle the format of the given file.
bool FBXImporter::CanRead(const std::string & pFile, IOSystem * pIOHandler, bool /*checkSig*/) const {
// at least ASCII-FBX files usually have a 'FBX' somewhere in their head
static const char *tokens[] = { " \n\r\n ", "fbx" };
static const char *tokens[] = { " \n\r\n " };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}

View File

@@ -36,6 +36,7 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#if !defined ASSIMP_BUILD_NO_M3D_IMPORTER || !(defined ASSIMP_BUILD_NO_EXPORT || defined ASSIMP_BUILD_NO_M3D_EXPORTER)
@@ -102,68 +103,15 @@ M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &b
ai_assert(nullptr != pIOHandler);
}
// Security fix: Validate buffer size and content before processing
if (buffer.empty()) {
ASSIMP_LOG_ERROR("M3D: Empty buffer provided");
m3d_ = nullptr;
return;
}
// Check for minimum valid M3D file size (header + basic structure)
const size_t MIN_VALID_M3D_SIZE = 100; // Minimum reasonable size for a valid M3D file
if (buffer.size() < MIN_VALID_M3D_SIZE) {
ASSIMP_LOG_ERROR("M3D: Buffer too small to be a valid M3D file");
m3d_ = nullptr;
return;
}
// Validate M3D magic signature to ensure this is actually an M3D file
// M3D files should start with "3DMO" or "3dmo" magic signature
if (buffer.size() >= 4) {
bool valid_signature = false;
// Check for "3DMO" (uppercase)
if (buffer[0] == '3' && buffer[1] == 'D' && buffer[2] == 'M' && buffer[3] == 'O') {
valid_signature = true;
}
// Check for "3dmo" (lowercase)
else if (buffer[0] == '3' && buffer[1] == 'd' && buffer[2] == 'm' && buffer[3] == 'o') {
valid_signature = true;
}
if (!valid_signature) {
ASSIMP_LOG_ERROR("M3D: Invalid file signature - not a valid M3D file");
m3d_ = nullptr;
return;
}
}
// Create a safe copy of the buffer with guard pages/validation
// This helps prevent buffer overflows from affecting the main process
std::vector<unsigned char> safe_buffer = buffer;
// Add a guard page at the end to catch any overflow attempts
// Note: This is a defensive measure, not a complete fix for the underlying issue
safe_buffer.resize(safe_buffer.size() + 1);
safe_buffer.back() = 0xFF; // Guard byte
#ifdef ASSIMP_USE_M3D_READFILECB
// pass this IOHandler to the C callback in a thread-local pointer
m3dimporter_pIOHandler = pIOHandler;
m3d_ = m3d_load(const_cast<unsigned char *>(safe_buffer.data()), m3dimporter_readfile, free, nullptr);
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
// Clear the C callback
m3dimporter_pIOHandler = nullptr;
#else
m3d_ = m3d_load(const_cast<unsigned char *>(safe_buffer.data()), nullptr, nullptr, nullptr);
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
#endif
// Verify the guard byte wasn't overwritten (indicating potential buffer overflow)
if (safe_buffer.empty() || safe_buffer.back() != 0xFF) {
ASSIMP_LOG_ERROR("M3D: Potential buffer overflow detected during loading");
if (m3d_) {
m3d_free(m3d_);
m3d_ = nullptr;
}
}
}
M3DWrapper::~M3DWrapper() {
@@ -199,4 +147,4 @@ void M3DWrapper::ClearSave() {
}
} // namespace Assimp
#endif
#endif

View File

@@ -72,7 +72,7 @@ public:
/// Construct an M3D model from provided buffer
/// @note The m3d.h SDK function does not mark the data as const. Have assumed it does not write.
/// SECURITY: Buffer size validation and guard pages added to mitigate potential overflows
/// BUG: SECURITY: The m3d.h SDK cannot be informed of the buffer size. BUFFER OVERFLOW IS CERTAIN
explicit M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer);
/// Theclasss destructor.

View File

@@ -1038,27 +1038,21 @@ size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remap
const size_t maxSize = GetMaxByteSize();
if (elemSize > maxSize) {
throw DeadlyImportError("GLTF: elemSize ", elemSize, " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
}
const size_t maxCount = (maxSize - elemSize) / stride + 1;
if (count > maxCount) {
throw DeadlyImportError("GLTF: count ", count, " > maxCount ", maxCount, " in ", getContextForErrorMessages(id, name));
}
outData = new T[usedCount];
if (remappingIndices != nullptr) {
const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
for (size_t i = 0; i < usedCount; ++i) {
size_t srcIdx = (*remappingIndices)[i];
if (srcIdx >= count) {
throw DeadlyImportError("GLTF: index ", srcIdx, " >= count ", count, " in ", getContextForErrorMessages(id, name));
if (srcIdx >= maxIndexCount) {
throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
}
memcpy(outData + i, data + srcIdx * stride, elemSize);
}
} else { // non-indexed cases
if (usedCount * stride > maxSize) {
throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
}
if (stride == elemSize && targetElemSize == elemSize) {
memcpy(outData, data, totalSize);
} else {

View File

@@ -556,6 +556,12 @@ void glTF2Exporter::GetMatTexProp(const aiMaterial &mat, unsigned int &prop, con
mat.Get(textureKey.c_str(), tt, slot, prop);
}
void glTF2Exporter::GetMatTexProp(const aiMaterial &mat, float &prop, const char *propName, aiTextureType tt, unsigned int slot) {
std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
mat.Get(textureKey.c_str(), tt, slot, prop);
}
void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0) {
if (mat.GetTextureCount(tt) == 0) {
return;
@@ -646,7 +652,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, NormalTextureInfo &prop, ai
if (texture) {
// GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
mat.Get(AI_MATKEY_GLTF_TEXTURE_SCALE(tt, slot), prop.scale);
GetMatTexProp(mat, prop.scale, "scale", tt, slot);
}
}
@@ -657,7 +663,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, OcclusionTextureInfo &prop,
if (texture) {
// GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
mat.Get(AI_MATKEY_GLTF_TEXTURE_STRENGTH(tt, slot), prop.strength);
GetMatTexProp(mat, prop.strength, "strength", tt, slot);
}
}

View File

@@ -110,6 +110,7 @@ protected:
void WriteBinaryData(IOStream *outfile, std::size_t sceneLength);
void GetTexSampler(const aiMaterial &mat, glTFCommon::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
void GetMatTexProp(const aiMaterial &mat, unsigned int &prop, const char *propName, aiTextureType tt, unsigned int idx);
void GetMatTexProp(const aiMaterial &mat, float &prop, const char *propName, aiTextureType tt, unsigned int idx);
void GetMatTex(const aiMaterial &mat, glTFCommon::Ref<glTF2::Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot);
void GetMatTex(const aiMaterial &mat, glTF2::TextureInfo &prop, aiTextureType tt, unsigned int slot);
void GetMatTex(const aiMaterial &mat, glTF2::NormalTextureInfo &prop, aiTextureType tt, unsigned int slot);

View File

@@ -237,7 +237,8 @@ static void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset
SetMaterialTextureProperty(embeddedTexIdxs, r, static_cast<TextureInfo>(prop), mat, texType, texSlot);
if (prop.texture && prop.texture->source) {
mat->AddProperty(&prop.strength, 1, AI_MATKEY_GLTF_TEXTURE_STRENGTH(texType, texSlot));
std::string textureStrengthKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + "strength";
mat->AddProperty(&prop.strength, 1, textureStrengthKey.c_str(), texType, texSlot);
}
}